diff --git a/.browserslistrc b/.browserslistrc new file mode 100644 index 0000000..dc3bc09 --- /dev/null +++ b/.browserslistrc @@ -0,0 +1,4 @@ +> 1% +last 2 versions +not dead +not ie 11 diff --git a/.commitlintrc.cjs b/.commitlintrc.cjs new file mode 100644 index 0000000..151ead3 --- /dev/null +++ b/.commitlintrc.cjs @@ -0,0 +1,107 @@ +const fs = require('fs'); +const path = require('path'); +const { execSync } = require('child_process'); + +const scopes = fs + .readdirSync(path.resolve(__dirname, 'src'), { withFileTypes: true }) + .filter((dirent) => dirent.isDirectory()) + .map((dirent) => dirent.name.replace(/s$/, '')); + +// precomputed scope +const scopeComplete = execSync('git status --porcelain || true') + .toString() + .trim() + .split('\n') + .find((r) => ~r.indexOf('M src')) + ?.replace(/(\/)/g, '%%') + ?.match(/src%%((\w|-)*)/)?.[1] + ?.replace(/s$/, ''); + +/** @type {import('cz-git').UserConfig} */ +module.exports = { + ignores: [(commit) => commit.includes('init')], + extends: ['@commitlint/config-conventional'], + rules: { + 'body-leading-blank': [2, 'always'], + 'footer-leading-blank': [1, 'always'], + 'header-max-length': [2, 'always', 108], + 'subject-empty': [2, 'never'], + 'type-empty': [2, 'never'], + 'subject-case': [0], + 'type-enum': [ + 2, + 'always', + [ + 'feat', + 'fix', + 'perf', + 'style', + 'docs', + 'test', + 'refactor', + 'build', + 'ci', + 'chore', + 'revert', + 'wip', + 'workflow', + 'types', + 'release', + ], + ], + }, + prompt: { + /** @use `yarn commit :f` */ + alias: { + f: 'docs: fix typos', + r: 'docs: update README', + s: 'style: update code format', + b: 'build: bump dependencies', + c: 'chore: update config', + }, + customScopesAlign: !scopeComplete ? 'top' : 'bottom', + defaultScope: scopeComplete, + scopes: [...scopes, 'mock'], + allowEmptyIssuePrefixs: false, + allowCustomIssuePrefixs: false, + + // English + typesAppend: [ + { value: 'wip', name: 'wip: work in process' }, + { value: 'workflow', name: 'workflow: workflow improvements' }, + { value: 'types', name: 'types: type definition file changes' }, + ], + + // 中英文对照版 + // messages: { + // type: '选择你要提交的类型 :', + // scope: '选择一个提交范围 (可选):', + // customScope: '请输入自定义的提交范围 :', + // subject: '填写简短精炼的变更描述 :\n', + // body: '填写更加详细的变更描述 (可选)。使用 "|" 换行 :\n', + // breaking: '列举非兼容性重大的变更 (可选)。使用 "|" 换行 :\n', + // footerPrefixsSelect: '选择关联issue前缀 (可选):', + // customFooterPrefixs: '输入自定义issue前缀 :', + // footer: '列举关联issue (可选) 例如: #31, #I3244 :\n', + // confirmCommit: '是否提交或修改commit ?', + // }, + // types: [ + // { value: 'feat', name: 'feat: 新增功能' }, + // { value: 'fix', name: 'fix: 修复缺陷' }, + // { value: 'docs', name: 'docs: 文档变更' }, + // { value: 'style', name: 'style: 代码格式' }, + // { value: 'refactor', name: 'refactor: 代码重构' }, + // { value: 'perf', name: 'perf: 性能优化' }, + // { value: 'test', name: 'test: 添加疏漏测试或已有测试改动' }, + // { value: 'build', name: 'build: 构建流程、外部依赖变更 (如升级 npm 包、修改打包配置等)' }, + // { value: 'ci', name: 'ci: 修改 CI 配置、脚本' }, + // { value: 'revert', name: 'revert: 回滚 commit' }, + // { value: 'chore', name: 'chore: 对构建过程或辅助工具和库的更改 (不影响源文件、测试用例)' }, + // { value: 'wip', name: 'wip: 正在开发中' }, + // { value: 'workflow', name: 'workflow: 工作流程改进' }, + // { value: 'types', name: 'types: 类型定义文件修改' }, + // ], + // emptyScopesAlias: 'empty: 不填写', + // customScopesAlias: 'custom: 自定义', + }, +}; diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..8617652 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,3 @@ +node_modules/ +dist/ +.vscode/ diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..dccf841 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,19 @@ +root = true + +[*] +charset=utf-8 +end_of_line=lf +insert_final_newline=true +indent_style=space +indent_size=2 +max_line_length = 100 + +[*.{yml,yaml,json}] +indent_style = space +indent_size = 2 + +[*.md] +trim_trailing_whitespace = false + +[Makefile] +indent_style = tab diff --git a/.env.nongjingquan b/.env.nongjingquan new file mode 100644 index 0000000..9452a52 --- /dev/null +++ b/.env.nongjingquan @@ -0,0 +1,45 @@ +# Whether to open mock +VITE_USE_MOCK = true + +# public path +VITE_PUBLIC_PATH = / + +# Whether to enable gzip or brotli compression +# Optional: gzip | brotli | none +# If you need multiple forms, you can use `,` to separate +VITE_BUILD_COMPRESS = 'none' + + +# Basic interface address SPA +# 农经权档案查询 +VITE_GLOB_API_URL=http://192.168.10.106:9640 + +VITE_GLOB_INFO_IMAGE_URL=http://120.222.154.48:6050 + +VITE_GLOB_INFO_IMAGE_URL=http://120.222.154.48:6050 + +# File upload address, optional +# It can be forwarded by nginx or write the actual address directly +VITE_GLOB_UPLOAD_URL=http://120.222.154.7:6050 + +# Interface prefix + +VITE_GLOB_API_URL_PREFIX= + +VITE_GLOB_APP_TITLE = 农经权档案查询 + +VITE_GLOB_APP_EN_TITLE = Basic Framework + +VITE_GLOB_APP_LOGO = /logo.png + +# VITE_GLOB_APP_MANAGEMENT_UNIT = 管理单位:临沂市自然资源和规划局 + +VITE_GLOB_APP_TECHINICAL_SUPPORT = 技术⽀持:山东慧创信息科技有限公司 + +VITE_GLOB_APP_VERSIONS = 系统版本:V1.0 + +VITE_GLOB_YINGXIANG_SERVER = http://192.168.31.205:8080/geoserver/ne/wms?service=WMS&version=1.1.0&request=GetMap&layers=ne:linyitif&styles=&bbox={bbox-epsg-3857}&width=256&height=256&srs=EPSG:3857&format=image/png&TRANSPARENT=TRUE + +VITE_GLOB_FILE_PREVIEW = http://120.222.154.7:6081 + + diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..67ac532 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,16 @@ + +*.sh +node_modules +*.md +*.woff +*.ttf +.vscode +.idea +dist +/public +/docs +.husky +.local +/bin +Dockerfile +package.json diff --git a/.eslintrc.cjs b/.eslintrc.cjs new file mode 100644 index 0000000..98fc3ef --- /dev/null +++ b/.eslintrc.cjs @@ -0,0 +1,7 @@ +module.exports = { + root: true, + extends: ['@vben'], + rules: { + 'no-undef': 'off', + }, +}; diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..d4e5bd3 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,11 @@ +# https://docs.github.com/cn/get-started/getting-started-with-git/configuring-git-to-handle-line-endings + +# Automatically normalize line endings (to LF) for all text-based files. +* text=auto eol=lf + +# Declare files that will always have CRLF line endings on checkout. +*.{cmd,[cC][mM][dD]} text eol=crlf +*.{bat,[bB][aA][tT]} text eol=crlf + +# Denote all files that are truly binary and should not be modified. +*.{ico,png,jpg,jpeg,gif,webp,svg,woff,woff2} binary \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..090afeb --- /dev/null +++ b/.gitignore @@ -0,0 +1,39 @@ +node_modules +.DS_Store +dist +dist.zip +.cache +.turbo + +tests/server/static +tests/server/static/upload + +.local +# local env files +.env.local +.env.*.local +.eslintcache +.env +.env.analyze +.env.development +.env.dikongganzhi +.env.production +# Log files +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +. +# Editor directories and files +.idea +# .vscode +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +package-lock.json +pnpm-lock.yaml + +.history diff --git a/.gitpod.yml b/.gitpod.yml new file mode 100644 index 0000000..866381f --- /dev/null +++ b/.gitpod.yml @@ -0,0 +1,6 @@ +ports: + - port: 3344 + onOpen: open-preview +tasks: + - init: pnpm install + command: pnpm run dev diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..29f68cf --- /dev/null +++ b/.npmrc @@ -0,0 +1,7 @@ +public-hoist-pattern[]=husky +public-hoist-pattern[]=*eslint* +public-hoist-pattern[]=*prettier* +public-hoist-pattern[]=lint-staged +public-hoist-pattern[]=*stylelint* +public-hoist-pattern[]=@commitlint/cli +public-hoist-pattern[]=@vben/eslint-config diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..24531e6 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,12 @@ +dist +.local +.output.js +node_modules + +**/*.svg +**/*.sh + +public +.npmrc + +*-lock.yaml diff --git a/.prettierrc.cjs b/.prettierrc.cjs new file mode 100644 index 0000000..4a24e88 --- /dev/null +++ b/.prettierrc.cjs @@ -0,0 +1,19 @@ +module.exports = { + printWidth: 100, + semi: true, + vueIndentScriptAndStyle: true, + singleQuote: true, + trailingComma: 'all', + proseWrap: 'never', + htmlWhitespaceSensitivity: 'strict', + endOfLine: 'auto', + plugins: ['prettier-plugin-packagejson'], + overrides: [ + { + files: '.*rc', + options: { + parser: 'json', + }, + }, + ], +}; diff --git a/.stylelintignore b/.stylelintignore new file mode 100644 index 0000000..6cd69e0 --- /dev/null +++ b/.stylelintignore @@ -0,0 +1,2 @@ +dist +public diff --git a/.stylelintrc.cjs b/.stylelintrc.cjs new file mode 100644 index 0000000..65320e7 --- /dev/null +++ b/.stylelintrc.cjs @@ -0,0 +1,4 @@ +module.exports = { + root: true, + extends: ['@vben/stylelint-config'], +}; diff --git a/hc/hc.css b/hc/hc.css new file mode 100644 index 0000000..e69de29 diff --git a/index.html b/index.html new file mode 100644 index 0000000..01fe8d9 --- /dev/null +++ b/index.html @@ -0,0 +1,177 @@ + + + + + + + + <%= VITE_GLOB_APP_TITLE %> + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+ +
+
<%= VITE_GLOB_APP_TITLE %>
+
+
+
+ + + + diff --git a/internal/eslint-config/.eslintignore b/internal/eslint-config/.eslintignore new file mode 100644 index 0000000..cef44b3 --- /dev/null +++ b/internal/eslint-config/.eslintignore @@ -0,0 +1,9 @@ + +*.sh +node_modules +*.md +*.woff +*.ttf +.turbo +dist +package.json diff --git a/internal/eslint-config/.eslintrc.cjs b/internal/eslint-config/.eslintrc.cjs new file mode 100644 index 0000000..cd27a19 --- /dev/null +++ b/internal/eslint-config/.eslintrc.cjs @@ -0,0 +1,4 @@ +module.exports = { + root: true, + extends: ['@vben/eslint-config/strict'], +}; diff --git a/internal/eslint-config/build.config.ts b/internal/eslint-config/build.config.ts new file mode 100644 index 0000000..08301e5 --- /dev/null +++ b/internal/eslint-config/build.config.ts @@ -0,0 +1,10 @@ +import { defineBuildConfig } from 'unbuild'; + +export default defineBuildConfig({ + clean: true, + entries: ['src/index', 'src/strict'], + declaration: true, + rollup: { + emitCJS: true, + }, +}); diff --git a/internal/eslint-config/package.json b/internal/eslint-config/package.json new file mode 100644 index 0000000..1288394 --- /dev/null +++ b/internal/eslint-config/package.json @@ -0,0 +1,50 @@ +{ + "name": "@vben/eslint-config", + "version": "1.0.0", + "private": true, + "homepage": "https://github.com/vbenjs/vue-vben-admin", + "bugs": { + "url": "https://github.com/vbenjs/vue-vben-admin/issues" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/vbenjs/vue-vben-admin.git", + "directory": "internal/eslint-config" + }, + "license": "MIT", + "type": "module", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "import": "./dist/index.mjs", + "require": "./dist/index.cjs" + }, + "./strict": { + "types": "./dist/strict.d.ts", + "import": "./dist/strict.mjs", + "require": "./dist/strict.cjs" + } + }, + "main": "./dist/index.cjs", + "module": "./dist/index.mjs", + "types": "./dist/index.d.ts", + "files": [ + "dist" + ], + "scripts": { + "clean": "pnpm rimraf .turbo node_modules dist", + "lint": "pnpm eslint .", + "stub": "pnpm unbuild --stub" + }, + "devDependencies": { + "@typescript-eslint/eslint-plugin": "^6.17.0", + "@typescript-eslint/parser": "^6.17.0", + "eslint": "^8.56.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-import": "^2.29.1", + "eslint-plugin-prettier": "^5.1.2", + "eslint-plugin-simple-import-sort": "^10.0.0", + "eslint-plugin-vue": "^9.19.2", + "vue-eslint-parser": "^9.3.2" + } +} diff --git a/internal/eslint-config/src/index.ts b/internal/eslint-config/src/index.ts new file mode 100644 index 0000000..1138bb3 --- /dev/null +++ b/internal/eslint-config/src/index.ts @@ -0,0 +1,91 @@ +export default { + env: { + browser: true, + node: true, + es6: true, + }, + parser: 'vue-eslint-parser', + parserOptions: { + parser: '@typescript-eslint/parser', + ecmaVersion: 2020, + sourceType: 'module', + jsxPragma: 'React', + ecmaFeatures: { + jsx: true, + }, + project: './tsconfig.*?.json', + createDefaultProgram: false, + extraFileExtensions: ['.vue'], + }, + plugins: ['vue', '@typescript-eslint', 'import'], + extends: [ + 'eslint:recommended', + 'plugin:vue/vue3-recommended', + 'plugin:@typescript-eslint/recommended', + 'plugin:prettier/recommended', + ], + rules: { + 'no-unused-vars': 'off', + 'no-case-declarations': 'off', + 'no-use-before-define': 'off', + 'space-before-function-paren': 'off', + + 'import/first': 'error', + 'import/newline-after-import': 'error', + 'import/no-duplicates': 'error', + + '@typescript-eslint/no-unused-vars': [ + 'error', + { + argsIgnorePattern: '^_', + varsIgnorePattern: '^_', + }, + ], + '@typescript-eslint/ban-ts-ignore': 'off', + '@typescript-eslint/ban-ts-comment': 'off', + '@typescript-eslint/ban-types': 'off', + '@typescript-eslint/explicit-function-return-type': 'off', + '@typescript-eslint/no-explicit-any': 'off', + '@typescript-eslint/no-var-requires': 'off', + '@typescript-eslint/no-empty-function': 'off', + '@typescript-eslint/no-use-before-define': 'off', + '@typescript-eslint/no-non-null-assertion': 'off', + '@typescript-eslint/explicit-module-boundary-types': 'off', + 'vue/script-setup-uses-vars': 'error', + 'vue/no-reserved-component-names': 'off', + 'vue/custom-event-name-casing': 'off', + 'vue/attributes-order': 'off', + 'vue/one-component-per-file': 'off', + 'vue/html-closing-bracket-newline': 'off', + 'vue/max-attributes-per-line': 'off', + 'vue/multiline-html-element-content-newline': 'off', + 'vue/singleline-html-element-content-newline': 'off', + 'vue/attribute-hyphenation': 'off', + 'vue/require-default-prop': 'off', + 'vue/require-explicit-emits': 'off', + 'vue/html-self-closing': [ + 'error', + { + html: { + void: 'always', + normal: 'never', + component: 'always', + }, + svg: 'always', + math: 'always', + }, + ], + 'vue/multi-word-component-names': 'off', + // 'sort-imports': [ + // 'error', + // { + // ignoreCase: true, + // ignoreDeclarationSort: false, + // ignoreMemberSort: false, + // memberSyntaxSortOrder: ['none', 'all', 'multiple', 'single'], + // allowSeparatedGroups: false, + // }, + // ], + }, + globals: { defineOptions: 'readonly' }, +}; diff --git a/internal/eslint-config/src/strict.ts b/internal/eslint-config/src/strict.ts new file mode 100644 index 0000000..5dbf5b7 --- /dev/null +++ b/internal/eslint-config/src/strict.ts @@ -0,0 +1,57 @@ +export default { + extends: ['@vben'], + plugins: ['simple-import-sort'], + rules: { + 'simple-import-sort/imports': 'error', + 'simple-import-sort/exports': 'error', + + '@typescript-eslint/ban-ts-comment': [ + 'error', + { + 'ts-expect-error': 'allow-with-description', + 'ts-ignore': 'allow-with-description', + 'ts-nocheck': 'allow-with-description', + 'ts-check': false, + }, + ], + + /** + * 【强制】关键字前后有一个空格 + * @link https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/keyword-spacing.md + */ + 'keyword-spacing': 'off', + '@typescript-eslint/keyword-spacing': [ + 'error', + { + before: true, + after: true, + overrides: { + return: { after: true }, + throw: { after: true }, + case: { after: true }, + }, + }, + ], + + /** + * 禁止出现空函数,普通函数(非 async/await/generator)、箭头函数、类上的方法除外 + * @link https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-empty-function.md + */ + 'no-empty-function': 'off', + '@typescript-eslint/no-empty-function': [ + 'error', + { + allow: ['arrowFunctions', 'functions', 'methods'], + }, + ], + + /** + * 优先使用 interface 而不是 type 定义对象类型 + * @link https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/consistent-type-definitions.md + */ + '@typescript-eslint/consistent-type-definitions': ['warn', 'interface'], + + 'vue/attributes-order': 'error', + 'vue/require-default-prop': 'error', + }, +}; diff --git a/internal/eslint-config/tsconfig.json b/internal/eslint-config/tsconfig.json new file mode 100644 index 0000000..cd27063 --- /dev/null +++ b/internal/eslint-config/tsconfig.json @@ -0,0 +1,5 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "extends": "@vben/ts-config/node.json", + "include": ["src"] +} diff --git a/internal/stylelint-config/.eslintignore b/internal/stylelint-config/.eslintignore new file mode 100644 index 0000000..cef44b3 --- /dev/null +++ b/internal/stylelint-config/.eslintignore @@ -0,0 +1,9 @@ + +*.sh +node_modules +*.md +*.woff +*.ttf +.turbo +dist +package.json diff --git a/internal/stylelint-config/.eslintrc.cjs b/internal/stylelint-config/.eslintrc.cjs new file mode 100644 index 0000000..cd27a19 --- /dev/null +++ b/internal/stylelint-config/.eslintrc.cjs @@ -0,0 +1,4 @@ +module.exports = { + root: true, + extends: ['@vben/eslint-config/strict'], +}; diff --git a/internal/stylelint-config/build.config.ts b/internal/stylelint-config/build.config.ts new file mode 100644 index 0000000..20c8b54 --- /dev/null +++ b/internal/stylelint-config/build.config.ts @@ -0,0 +1,10 @@ +import { defineBuildConfig } from 'unbuild'; + +export default defineBuildConfig({ + clean: true, + entries: ['src/index'], + declaration: true, + rollup: { + emitCJS: true, + }, +}); diff --git a/internal/stylelint-config/package.json b/internal/stylelint-config/package.json new file mode 100644 index 0000000..6a3ba22 --- /dev/null +++ b/internal/stylelint-config/package.json @@ -0,0 +1,49 @@ +{ + "name": "@vben/stylelint-config", + "version": "1.0.0", + "private": true, + "homepage": "https://github.com/vbenjs/vue-vben-admin", + "bugs": { + "url": "https://github.com/vbenjs/vue-vben-admin/issues" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/vbenjs/vue-vben-admin.git", + "directory": "internal/stylelint-config" + }, + "license": "MIT", + "type": "module", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "import": "./dist/index.mjs", + "require": "./dist/index.cjs" + } + }, + "main": "./dist/index.cjs", + "module": "./dist/index.mjs", + "types": "./dist/index.d.ts", + "files": [ + "dist" + ], + "scripts": { + "clean": "pnpm rimraf .turbo node_modules dist", + "lint": "pnpm eslint .", + "stub": "pnpm unbuild --stub" + }, + "devDependencies": { + "postcss": "^8.4.33", + "postcss-html": "^1.5.0", + "postcss-less": "^6.0.0", + "postcss-scss": "^4.0.9", + "prettier": "^3.1.1", + "stylelint": "^16.1.0", + "stylelint-config-property-sort-order-smacss": "^10.0.0", + "stylelint-config-recommended-scss": "^14.0.0", + "stylelint-config-recommended-vue": "^1.5.0", + "stylelint-config-standard": "^36.0.0", + "stylelint-config-standard-scss": "^13.0.0", + "stylelint-order": "^6.0.4", + "stylelint-prettier": "^5.0.0" + } +} diff --git a/internal/stylelint-config/src/index.ts b/internal/stylelint-config/src/index.ts new file mode 100644 index 0000000..8b15456 --- /dev/null +++ b/internal/stylelint-config/src/index.ts @@ -0,0 +1,92 @@ +export default { + extends: ['stylelint-config-standard', 'stylelint-config-property-sort-order-smacss'], + plugins: ['stylelint-order', 'stylelint-prettier'], + // customSyntax: 'postcss-html', + overrides: [ + { + files: ['**/*.(css|html|vue)'], + customSyntax: 'postcss-html', + }, + { + files: ['*.less', '**/*.less'], + customSyntax: 'postcss-less', + extends: ['stylelint-config-standard', 'stylelint-config-recommended-vue'], + }, + { + files: ['*.scss', '**/*.scss'], + customSyntax: 'postcss-scss', + extends: ['stylelint-config-standard-scss', 'stylelint-config-recommended-vue/scss'], + rule: { + 'scss/percent-placeholder-pattern': null, + }, + }, + ], + rules: { + 'prettier/prettier': true, + 'media-feature-range-notation': null, + 'selector-not-notation': null, + 'import-notation': null, + 'function-no-unknown': null, + 'selector-class-pattern': null, + 'selector-pseudo-class-no-unknown': [ + true, + { + ignorePseudoClasses: ['global', 'deep'], + }, + ], + 'selector-pseudo-element-no-unknown': [ + true, + { + ignorePseudoElements: ['v-deep'], + }, + ], + 'at-rule-no-unknown': [ + true, + { + ignoreAtRules: [ + 'tailwind', + 'apply', + 'variants', + 'responsive', + 'screen', + 'function', + 'if', + 'each', + 'include', + 'mixin', + 'extend', + ], + }, + ], + '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: 'error' }, + ], + }, + ignoreFiles: ['**/*.js', '**/*.jsx', '**/*.tsx', '**/*.ts'], +}; diff --git a/internal/stylelint-config/tsconfig.json b/internal/stylelint-config/tsconfig.json new file mode 100644 index 0000000..cd27063 --- /dev/null +++ b/internal/stylelint-config/tsconfig.json @@ -0,0 +1,5 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "extends": "@vben/ts-config/node.json", + "include": ["src"] +} diff --git a/internal/ts-config/base.json b/internal/ts-config/base.json new file mode 100644 index 0000000..8b90054 --- /dev/null +++ b/internal/ts-config/base.json @@ -0,0 +1,27 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "display": "Base", + "compilerOptions": { + "target": "ESNext", + "module": "ESNext", + "moduleResolution": "bundler", + "strict": true, + "declaration": true, + "noImplicitOverride": true, + "noUnusedLocals": true, + "esModuleInterop": true, + "useUnknownInCatchVariables": false, + "composite": false, + "declarationMap": false, + "forceConsistentCasingInFileNames": true, + "inlineSources": false, + "isolatedModules": true, + "skipLibCheck": true, + "noUnusedParameters": false, + "preserveWatchOutput": true, + "experimentalDecorators": true, + "resolveJsonModule": true, + "removeComments": true + }, + "exclude": ["**/node_modules/**", "**/dist/**"] +} diff --git a/internal/ts-config/node-server.json b/internal/ts-config/node-server.json new file mode 100644 index 0000000..e27374a --- /dev/null +++ b/internal/ts-config/node-server.json @@ -0,0 +1,18 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "display": "Node Server Config", + "extends": "./base.json", + "compilerOptions": { + "module": "commonjs", + "declaration": false, + "removeComments": true, + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "target": "es6", + "sourceMap": false, + "esModuleInterop": true, + "outDir": "./dist", + "baseUrl": "./" + }, + "exclude": ["node_modules"] +} diff --git a/internal/ts-config/node.json b/internal/ts-config/node.json new file mode 100644 index 0000000..cdd365f --- /dev/null +++ b/internal/ts-config/node.json @@ -0,0 +1,12 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "display": "Node Config", + "extends": "./base.json", + "compilerOptions": { + "lib": ["ESNext"], + "noImplicitAny": true, + "sourceMap": true, + "noEmit": true, + "baseUrl": "./" + } +} diff --git a/internal/ts-config/package.json b/internal/ts-config/package.json new file mode 100644 index 0000000..9a41a22 --- /dev/null +++ b/internal/ts-config/package.json @@ -0,0 +1,26 @@ +{ + "name": "@vben/ts-config", + "version": "1.0.0", + "private": true, + "homepage": "https://github.com/vbenjs/vue-vben-admin", + "bugs": { + "url": "https://github.com/vbenjs/vue-vben-admin/issues" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/vbenjs/vue-vben-admin.git", + "directory": "internal/ts-config" + }, + "license": "MIT", + "type": "module", + "files": [ + "base.json", + "node.json", + "vue-app.json", + "node-server.json" + ], + "dependencies": { + "@types/node": "^20.10.6", + "vite": "^5.0.10" + } +} diff --git a/internal/ts-config/vue-app.json b/internal/ts-config/vue-app.json new file mode 100644 index 0000000..02f3fd2 --- /dev/null +++ b/internal/ts-config/vue-app.json @@ -0,0 +1,10 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "display": "Vue Application", + "extends": "./base.json", + "compilerOptions": { + "jsx": "preserve", + "lib": ["ESNext", "DOM"], + "noImplicitAny": false + } +} diff --git a/internal/vite-config/.eslintignore b/internal/vite-config/.eslintignore new file mode 100644 index 0000000..cef44b3 --- /dev/null +++ b/internal/vite-config/.eslintignore @@ -0,0 +1,9 @@ + +*.sh +node_modules +*.md +*.woff +*.ttf +.turbo +dist +package.json diff --git a/internal/vite-config/.eslintrc.cjs b/internal/vite-config/.eslintrc.cjs new file mode 100644 index 0000000..cd27a19 --- /dev/null +++ b/internal/vite-config/.eslintrc.cjs @@ -0,0 +1,4 @@ +module.exports = { + root: true, + extends: ['@vben/eslint-config/strict'], +}; diff --git a/internal/vite-config/build.config.ts b/internal/vite-config/build.config.ts new file mode 100644 index 0000000..20c8b54 --- /dev/null +++ b/internal/vite-config/build.config.ts @@ -0,0 +1,10 @@ +import { defineBuildConfig } from 'unbuild'; + +export default defineBuildConfig({ + clean: true, + entries: ['src/index'], + declaration: true, + rollup: { + emitCJS: true, + }, +}); diff --git a/internal/vite-config/package.json b/internal/vite-config/package.json new file mode 100644 index 0000000..35ae44b --- /dev/null +++ b/internal/vite-config/package.json @@ -0,0 +1,59 @@ +{ + "name": "@vben/vite-config", + "version": "1.0.0", + "private": true, + "homepage": "https://github.com/vbenjs/vue-vben-admin", + "bugs": { + "url": "https://github.com/vbenjs/vue-vben-admin/issues" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/vbenjs/vue-vben-admin.git", + "directory": "internal/vite-config" + }, + "license": "MIT", + "type": "module", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "import": "./dist/index.mjs", + "require": "./dist/index.cjs" + } + }, + "main": "./dist/index.cjs", + "module": "./dist/index.mjs", + "types": "./dist/index.d.ts", + "files": [ + "dist" + ], + "scripts": { + "clean": "pnpm rimraf .turbo node_modules dist", + "lint": "pnpm eslint .", + "stub": "pnpm unbuild --stub" + }, + "dependencies": { + "@ant-design/colors": "^7.0.2", + "vite": "^5.0.10" + }, + "devDependencies": { + "@types/fs-extra": "^11.0.4", + "@vitejs/plugin-vue": "^5.0.2", + "@vitejs/plugin-vue-jsx": "^3.1.0", + "ant-design-vue": "^4.0.8", + "dayjs": "^1.11.10", + "dotenv": "^16.3.1", + "fs-extra": "^11.2.0", + "less": "^4.2.0", + "picocolors": "^1.0.0", + "pkg-types": "^1.0.3", + "rollup-plugin-visualizer": "^5.12.0", + "sass": "^1.69.7", + "unocss": "0.58.3", + "vite-plugin-compression": "^0.5.1", + "vite-plugin-dts": "^3.7.0", + "vite-plugin-html": "^3.2.1", + "vite-plugin-mock": "^2.9.6", + "vite-plugin-purge-icons": "^0.10.0", + "vite-plugin-svg-icons": "^2.0.1" + } +} diff --git a/internal/vite-config/src/config/application.ts b/internal/vite-config/src/config/application.ts new file mode 100644 index 0000000..bd6d6ca --- /dev/null +++ b/internal/vite-config/src/config/application.ts @@ -0,0 +1,109 @@ +import { resolve } from 'node:path'; + +import dayjs from 'dayjs'; +import { readPackageJSON } from 'pkg-types'; +import { defineConfig, loadEnv, mergeConfig, type UserConfig } from 'vite'; + +import { createPlugins } from '../plugins'; +import { generateModifyVars } from '../utils/modifyVars'; +import { commonConfig } from './common'; + +interface DefineOptions { + overrides?: UserConfig; + options?: { + // + }; +} + +function defineApplicationConfig(defineOptions: DefineOptions = {}) { + const { overrides = {} } = defineOptions; + + return defineConfig(async ({ command, mode }) => { + const root = process.cwd(); + const isBuild = command === 'build'; + const { VITE_PUBLIC_PATH, VITE_USE_MOCK, VITE_BUILD_COMPRESS, VITE_ENABLE_ANALYZE } = loadEnv( + mode, + root, + ); + + const defineData = await createDefineData(root); + const plugins = await createPlugins({ + isBuild, + root, + enableAnalyze: VITE_ENABLE_ANALYZE === 'true', + enableMock: VITE_USE_MOCK === 'true', + compress: VITE_BUILD_COMPRESS, + }); + + const pathResolve = (pathname: string) => resolve(root, '.', pathname); + const timestamp = new Date().getTime(); + const applicationConfig: UserConfig = { + base: VITE_PUBLIC_PATH, + resolve: { + alias: [ + { + find: 'vue-i18n', + replacement: 'vue-i18n/dist/vue-i18n.cjs.js', + }, + // @/xxxx => src/xxxx + { + find: /@\//, + replacement: pathResolve('src') + '/', + }, + // #/xxxx => types/xxxx + { + find: /#\//, + replacement: pathResolve('types') + '/', + }, + ], + }, + define: defineData, + build: { + target: 'es2015', + cssTarget: 'chrome80', + rollupOptions: { + output: { + // 入口文件名 + entryFileNames: `assets/entry/[name]-[hash]-${timestamp}.js`, + manualChunks: { + vue: ['vue', 'pinia', 'vue-router'], + antd: ['ant-design-vue', '@ant-design/icons-vue'], + }, + }, + }, + }, + css: { + preprocessorOptions: { + less: { + modifyVars: generateModifyVars(), + javascriptEnabled: true, + }, + }, + }, + plugins, + }; + + const mergedConfig = mergeConfig(commonConfig(mode), applicationConfig); + + return mergeConfig(mergedConfig, overrides); + }); +} + +async function createDefineData(root: string) { + try { + const pkgJson = await readPackageJSON(root); + const { dependencies, devDependencies, name, version } = pkgJson; + + const __APP_INFO__ = { + pkg: { dependencies, devDependencies, name, version }, + lastBuildTime: dayjs().format('YYYY-MM-DD HH:mm:ss'), + }; + return { + __APP_INFO__: JSON.stringify(__APP_INFO__), + }; + } catch (error) { + return {}; + } +} + +export { defineApplicationConfig }; diff --git a/internal/vite-config/src/config/common.ts b/internal/vite-config/src/config/common.ts new file mode 100644 index 0000000..7c108b3 --- /dev/null +++ b/internal/vite-config/src/config/common.ts @@ -0,0 +1,22 @@ +import UnoCSS from 'unocss/vite'; +import { type UserConfig } from 'vite'; + +const commonConfig: (mode: string) => UserConfig = (mode) => ({ + server: { + host: true, + }, + esbuild: { + drop: mode === 'production' ? ['debugger'] : [], + }, + build: { + reportCompressedSize: false, + chunkSizeWarningLimit: 1500, + rollupOptions: { + // TODO: Prevent memory overflow + maxParallelFileOps: 3, + }, + }, + plugins: [UnoCSS()], +}); + +export { commonConfig }; diff --git a/internal/vite-config/src/config/package.ts b/internal/vite-config/src/config/package.ts new file mode 100644 index 0000000..ab83852 --- /dev/null +++ b/internal/vite-config/src/config/package.ts @@ -0,0 +1,42 @@ +import { readPackageJSON } from 'pkg-types'; +import { defineConfig, mergeConfig, type UserConfig } from 'vite'; +import dts from 'vite-plugin-dts'; + +import { commonConfig } from './common'; + +interface DefineOptions { + overrides?: UserConfig; + options?: { + // + }; +} + +function definePackageConfig(defineOptions: DefineOptions = {}) { + const { overrides = {} } = defineOptions; + const root = process.cwd(); + return defineConfig(async ({ mode }) => { + const { dependencies = {}, peerDependencies = {} } = await readPackageJSON(root); + const packageConfig: UserConfig = { + build: { + lib: { + entry: 'src/index.ts', + formats: ['es'], + fileName: () => 'index.mjs', + }, + rollupOptions: { + external: [...Object.keys(dependencies), ...Object.keys(peerDependencies)], + }, + }, + plugins: [ + dts({ + logLevel: 'error', + }), + ], + }; + const mergedConfig = mergeConfig(commonConfig(mode), packageConfig); + + return mergeConfig(mergedConfig, overrides); + }); +} + +export { definePackageConfig }; diff --git a/internal/vite-config/src/index.ts b/internal/vite-config/src/index.ts new file mode 100644 index 0000000..9ef1e80 --- /dev/null +++ b/internal/vite-config/src/index.ts @@ -0,0 +1,2 @@ +export * from './config/application'; +export * from './config/package'; diff --git a/internal/vite-config/src/plugins/appConfig.ts b/internal/vite-config/src/plugins/appConfig.ts new file mode 100644 index 0000000..7d50662 --- /dev/null +++ b/internal/vite-config/src/plugins/appConfig.ts @@ -0,0 +1,104 @@ +import colors from 'picocolors'; +import { readPackageJSON } from 'pkg-types'; +import { type PluginOption } from 'vite'; + +import { getEnvConfig } from '../utils/env'; +import { createContentHash } from '../utils/hash'; + +const GLOBAL_CONFIG_FILE_NAME = '_app.config.js'; +const PLUGIN_NAME = 'app-config'; + +async function createAppConfigPlugin({ + root, + isBuild, +}: { + root: string; + isBuild: boolean; +}): Promise { + let publicPath: string; + let source: string; + if (!isBuild) { + return { + name: PLUGIN_NAME, + }; + } + const { version = '' } = await readPackageJSON(root); + + return { + name: PLUGIN_NAME, + async configResolved(_config) { + const appTitle = _config?.env?.VITE_GLOB_APP_TITLE ?? ''; + // appTitle = appTitle.replace(/\s/g, '_').replace(/-/g, '_'); + publicPath = _config.base; + source = await getConfigSource(appTitle); + }, + async transformIndexHtml(html) { + publicPath = publicPath.endsWith('/') ? publicPath : `${publicPath}/`; + + const appConfigSrc = `${ + publicPath || '/' + }${GLOBAL_CONFIG_FILE_NAME}?v=${version}-${createContentHash(source)}`; + + return { + html, + tags: [ + { + tag: 'script', + attrs: { + src: appConfigSrc, + }, + }, + ], + }; + }, + async generateBundle() { + try { + this.emitFile({ + type: 'asset', + fileName: GLOBAL_CONFIG_FILE_NAME, + source, + }); + + console.log(colors.cyan(`✨configuration file is build successfully!`)); + } catch (error) { + console.log( + colors.red('configuration file configuration file failed to package:\n' + error), + ); + } + }, + }; +} + +/** + * Get the configuration file variable name + * @param env + */ +const getVariableName = (title: string) => { + function strToHex(str: string) { + const result: string[] = []; + for (let i = 0; i < str.length; ++i) { + const hex = str.charCodeAt(i).toString(16); + result.push(('000' + hex).slice(-4)); + } + return result.join('').toUpperCase(); + } + return `__PRODUCTION__${strToHex(title) || '__APP'}__CONF__`.toUpperCase().replace(/\s/g, ''); +}; + +async function getConfigSource(appTitle: string) { + const config = await getEnvConfig(); + const variableName = getVariableName(appTitle); + const windowVariable = `window.${variableName}`; + // Ensure that the variable will not be modified + let source = `${windowVariable}=${JSON.stringify(config)};`; + source += ` + Object.freeze(${windowVariable}); + Object.defineProperty(window, "${variableName}", { + configurable: false, + writable: false, + }); + `.replace(/\s/g, ''); + return source; +} + +export { createAppConfigPlugin }; diff --git a/internal/vite-config/src/plugins/compress.ts b/internal/vite-config/src/plugins/compress.ts new file mode 100644 index 0000000..8fc1397 --- /dev/null +++ b/internal/vite-config/src/plugins/compress.ts @@ -0,0 +1,38 @@ +/** + * Used to package and output gzip. Note that this does not work properly in Vite, the specific reason is still being investigated + * https://github.com/anncwb/vite-plugin-compression + */ +import type { PluginOption } from 'vite'; +import compressPlugin from 'vite-plugin-compression'; + +export function configCompressPlugin({ + compress, + deleteOriginFile = false, +}: { + compress: string; + deleteOriginFile?: boolean; +}): PluginOption[] { + const compressList = compress.split(','); + + const plugins: PluginOption[] = []; + + if (compressList.includes('gzip')) { + plugins.push( + compressPlugin({ + ext: '.gz', + deleteOriginFile, + }), + ); + } + + if (compressList.includes('brotli')) { + plugins.push( + compressPlugin({ + ext: '.br', + algorithm: 'brotliCompress', + deleteOriginFile, + }), + ); + } + return plugins; +} diff --git a/internal/vite-config/src/plugins/html.ts b/internal/vite-config/src/plugins/html.ts new file mode 100644 index 0000000..2623a28 --- /dev/null +++ b/internal/vite-config/src/plugins/html.ts @@ -0,0 +1,14 @@ +/** + * Plugin to minimize and use ejs template syntax in index.html. + * https://github.com/anncwb/vite-plugin-html + */ +import type { PluginOption } from 'vite'; +import { createHtmlPlugin } from 'vite-plugin-html'; + +export function configHtmlPlugin({ isBuild }: { isBuild: boolean }) { + const htmlPlugin: PluginOption[] = createHtmlPlugin({ + minify: isBuild, + viteNext: true, + }); + return htmlPlugin; +} diff --git a/internal/vite-config/src/plugins/index.ts b/internal/vite-config/src/plugins/index.ts new file mode 100644 index 0000000..b13fb39 --- /dev/null +++ b/internal/vite-config/src/plugins/index.ts @@ -0,0 +1,59 @@ +import vue from '@vitejs/plugin-vue'; +import vueJsx from '@vitejs/plugin-vue-jsx'; +import { type PluginOption } from 'vite'; +import purgeIcons from 'vite-plugin-purge-icons'; + +import { createAppConfigPlugin } from './appConfig'; +import { configCompressPlugin } from './compress'; +import { configHtmlPlugin } from './html'; +import { configMockPlugin } from './mock'; +import { configSvgIconsPlugin } from './svgSprite'; +import { configVisualizerConfig } from './visualizer'; + +interface Options { + isBuild: boolean; + root: string; + compress: string; + enableMock?: boolean; + enableAnalyze?: boolean; +} + +async function createPlugins({ isBuild, root, enableMock, compress, enableAnalyze }: Options) { + const vitePlugins: (PluginOption | PluginOption[])[] = [vue(), vueJsx()]; + + const appConfigPlugin = await createAppConfigPlugin({ root, isBuild }); + vitePlugins.push(appConfigPlugin); + + // vite-plugin-html + vitePlugins.push(configHtmlPlugin({ isBuild })); + + // vite-plugin-svg-icons + vitePlugins.push(configSvgIconsPlugin({ isBuild })); + + // vite-plugin-purge-icons + vitePlugins.push(purgeIcons()); + + // The following plugins only work in the production environment + if (isBuild) { + // rollup-plugin-gzip + vitePlugins.push( + configCompressPlugin({ + compress, + }), + ); + } + + // rollup-plugin-visualizer + if (enableAnalyze) { + vitePlugins.push(configVisualizerConfig()); + } + + // vite-plugin-mock + if (enableMock) { + vitePlugins.push(configMockPlugin({ isBuild })); + } + + return vitePlugins; +} + +export { createPlugins }; diff --git a/internal/vite-config/src/plugins/mock.ts b/internal/vite-config/src/plugins/mock.ts new file mode 100644 index 0000000..b47899c --- /dev/null +++ b/internal/vite-config/src/plugins/mock.ts @@ -0,0 +1,19 @@ +/** + * Mock plugin for development and production. + * https://github.com/anncwb/vite-plugin-mock + */ +import { viteMockServe } from 'vite-plugin-mock'; + +export function configMockPlugin({ isBuild }: { isBuild: boolean }) { + return viteMockServe({ + ignore: /^_/, + mockPath: 'mock', + localEnabled: !isBuild, + prodEnabled: isBuild, + injectCode: ` + import { setupProdMockServer } from '../mock/_createProductionServer'; + + setupProdMockServer(); + `, + }); +} diff --git a/internal/vite-config/src/plugins/svgSprite.ts b/internal/vite-config/src/plugins/svgSprite.ts new file mode 100644 index 0000000..659e5af --- /dev/null +++ b/internal/vite-config/src/plugins/svgSprite.ts @@ -0,0 +1,17 @@ +/** + * Vite Plugin for fast creating SVG sprites. + * https://github.com/anncwb/vite-plugin-svg-icons + */ + +import { resolve } from 'node:path'; + +import type { PluginOption } from 'vite'; +import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'; + +export function configSvgIconsPlugin({ isBuild }: { isBuild: boolean }) { + const svgIconsPlugin = createSvgIconsPlugin({ + iconDirs: [resolve(process.cwd(), 'src/assets/icons')], + svgoOptions: isBuild, + }); + return svgIconsPlugin as PluginOption; +} diff --git a/internal/vite-config/src/plugins/visualizer.ts b/internal/vite-config/src/plugins/visualizer.ts new file mode 100644 index 0000000..0b6ba62 --- /dev/null +++ b/internal/vite-config/src/plugins/visualizer.ts @@ -0,0 +1,14 @@ +/** + * Package file volume analysis + */ +import visualizer from 'rollup-plugin-visualizer'; +import { type PluginOption } from 'vite'; + +export function configVisualizerConfig() { + return visualizer({ + filename: './node_modules/.cache/visualizer/stats.html', + open: true, + gzipSize: true, + brotliSize: true, + }) as PluginOption; +} diff --git a/internal/vite-config/src/utils/env.ts b/internal/vite-config/src/utils/env.ts new file mode 100644 index 0000000..c84ea94 --- /dev/null +++ b/internal/vite-config/src/utils/env.ts @@ -0,0 +1,49 @@ +import { join } from 'node:path'; + +import dotenv from 'dotenv'; +import { readFile } from 'fs-extra'; + +/** + * 获取当前环境下生效的配置文件名 + */ +function getConfFiles() { + const script = process.env.npm_lifecycle_script as string; + const reg = new RegExp('--mode ([a-z_\\d]+)'); + const result = reg.exec(script); + if (result) { + const mode = result[1]; + return ['.env', `.env.${mode}`]; + } + return ['.env', '.env.production']; +} + +/** + * Get the environment variables starting with the specified prefix + * @param match prefix + * @param confFiles ext + */ +export async function getEnvConfig( + match = 'VITE_GLOB_', + confFiles = getConfFiles(), +): Promise<{ + [key: string]: string; +}> { + let envConfig = {}; + + for (const confFile of confFiles) { + try { + const envPath = await readFile(join(process.cwd(), confFile), { encoding: 'utf8' }); + const env = dotenv.parse(envPath); + envConfig = { ...envConfig, ...env }; + } catch (e) { + console.error(`Error in parsing ${confFile}`, e); + } + } + const reg = new RegExp(`^(${match})`); + Object.keys(envConfig).forEach((key) => { + if (!reg.test(key)) { + Reflect.deleteProperty(envConfig, key); + } + }); + return envConfig; +} diff --git a/internal/vite-config/src/utils/hash.ts b/internal/vite-config/src/utils/hash.ts new file mode 100644 index 0000000..0b5a7c9 --- /dev/null +++ b/internal/vite-config/src/utils/hash.ts @@ -0,0 +1,16 @@ +import { createHash } from 'node:crypto'; + +function createContentHash(content: string, hashLSize = 12) { + const hash = createHash('sha256').update(content); + return hash.digest('hex').slice(0, hashLSize); +} +function strToHex(str: string) { + const result: string[] = []; + for (let i = 0; i < str.length; ++i) { + const hex = str.charCodeAt(i).toString(16); + result.push(('000' + hex).slice(-4)); + } + return result.join('').toUpperCase(); +} + +export { createContentHash, strToHex }; diff --git a/internal/vite-config/src/utils/modifyVars.ts b/internal/vite-config/src/utils/modifyVars.ts new file mode 100644 index 0000000..0554343 --- /dev/null +++ b/internal/vite-config/src/utils/modifyVars.ts @@ -0,0 +1,47 @@ +import { resolve } from 'node:path'; + +import { generate } from '@ant-design/colors'; +// @ts-ignore: typo +/* import { getThemeVariables } from 'ant-design-vue/dist/theme'; */ +import { theme } from 'ant-design-vue/lib'; +import convertLegacyToken from 'ant-design-vue/lib/theme/convertLegacyToken'; + +const { defaultAlgorithm, defaultSeed } = theme; +const primaryColor = '#0960bd'; + +function generateAntColors(color: string, theme: 'default' | 'dark' = 'default') { + return generate(color, { + theme, + }); +} + +/** + * less global variable + */ +export function generateModifyVars() { + const palettes = generateAntColors(primaryColor); + const primary = palettes[5]; + const primaryColorObj: Record = {}; + + for (let index = 0; index < 10; index++) { + primaryColorObj[`primary-${index + 1}`] = palettes[index]; + } + // const modifyVars = getThemeVariables(); + const mapToken = defaultAlgorithm(defaultSeed); + const v3Token = convertLegacyToken(mapToken); + return { + ...v3Token, + // reference: Avoid repeated references + hack: `true; @import (reference) "${resolve('src/design/config.less')}";`, + 'primary-color': primary, + ...primaryColorObj, + 'info-color': primary, + 'processing-color': primary, + 'success-color': '#55D187', // Success color + 'error-color': '#ED6F6F', // False color + 'warning-color': '#EFBD47', // Warning color + 'font-size-base': '14px', // Main font size + 'border-radius-base': '2px', // Component/float fillet + 'link-color': primary, // Link color + }; +} diff --git a/internal/vite-config/tsconfig.json b/internal/vite-config/tsconfig.json new file mode 100644 index 0000000..cd27063 --- /dev/null +++ b/internal/vite-config/tsconfig.json @@ -0,0 +1,5 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "extends": "@vben/ts-config/node.json", + "include": ["src"] +} diff --git a/lib/vform/designer.style.css b/lib/vform/designer.style.css new file mode 100644 index 0000000..a6ac1a2 --- /dev/null +++ b/lib/vform/designer.style.css @@ -0,0 +1,16 @@ +@charset "UTF-8";.primary-color[data-v-8002b89a]{color:#409eff}.background-opacity[data-v-8002b89a]{background:rgba(64,158,255,.6)}.form-widget-list .ghost[data-v-8002b89a]{content:"";font-size:0;height:3px;box-sizing:border-box;background:#409EFF;border:2px solid #409EFF;outline-width:0;padding:0;overflow:hidden}.el-form-item .el-rate[data-v-8002b89a]{margin-top:8px}.el-form-item--medium .el-radio[data-v-8002b89a]{line-height:36px!important}.el-form-item--medium .el-rate[data-v-8002b89a]{margin-top:8px}.el-form-item--small .el-radio[data-v-8002b89a]{line-height:32px!important}.el-form-item--small .el-rate[data-v-8002b89a]{margin-top:6px}.el-form-item--mini .el-radio[data-v-8002b89a]{line-height:28px!important}.el-form-item--mini .el-rate[data-v-8002b89a]{margin-top:4px}.el-card[data-v-8002b89a]{margin-top:3px;margin-bottom:3px}input[type=password][data-v-8002b89a]::-ms-reveal{display:none}.auto-full-width.el-date-editor.el-input[data-v-8002b89a],.auto-full-width.el-date-editor.el-input__inner[data-v-8002b89a]{width:100%!important}[data-v-8002b89a]::-webkit-scrollbar{width:8px;height:8px}[data-v-8002b89a]::-webkit-scrollbar-track{width:8px;background:rgba(16,31,28,.1);-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-8002b89a]::-webkit-scrollbar-thumb{background-color:#101f1c59;background-clip:padding-box;min-height:28px;-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-8002b89a]::-webkit-scrollbar-thumb:hover{background-color:#101f1cd9}*[data-v-8002b89a]{scrollbar-color:#e5e5e5 #f7f7f9;scrollbar-width:thin}.svg-icon[data-v-8002b89a]{width:1.1em;height:1.1em;margin-left:.35em;margin-right:.35em;vertical-align:-.15em;fill:currentColor;overflow:hidden;display:inline-block}.primary-color[data-v-335b6326]{color:#409eff}.background-opacity[data-v-335b6326]{background:rgba(64,158,255,.6)}.form-widget-list .ghost[data-v-335b6326]{content:"";font-size:0;height:3px;box-sizing:border-box;background:#409EFF;border:2px solid #409EFF;outline-width:0;padding:0;overflow:hidden}.el-form-item .el-rate[data-v-335b6326]{margin-top:8px}.el-form-item--medium .el-radio[data-v-335b6326]{line-height:36px!important}.el-form-item--medium .el-rate[data-v-335b6326]{margin-top:8px}.el-form-item--small .el-radio[data-v-335b6326]{line-height:32px!important}.el-form-item--small .el-rate[data-v-335b6326]{margin-top:6px}.el-form-item--mini .el-radio[data-v-335b6326]{line-height:28px!important}.el-form-item--mini .el-rate[data-v-335b6326]{margin-top:4px}.el-card[data-v-335b6326]{margin-top:3px;margin-bottom:3px}input[type=password][data-v-335b6326]::-ms-reveal{display:none}.auto-full-width.el-date-editor.el-input[data-v-335b6326],.auto-full-width.el-date-editor.el-input__inner[data-v-335b6326]{width:100%!important}[data-v-335b6326]::-webkit-scrollbar{width:8px;height:8px}[data-v-335b6326]::-webkit-scrollbar-track{width:8px;background:rgba(16,31,28,.1);-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-335b6326]::-webkit-scrollbar-thumb{background-color:#101f1c59;background-clip:padding-box;min-height:28px;-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-335b6326]::-webkit-scrollbar-thumb:hover{background-color:#101f1cd9}*[data-v-335b6326]{scrollbar-color:#e5e5e5 #f7f7f9;scrollbar-width:thin}.color-svg-icon[data-v-335b6326]{-webkit-font-smoothing:antialiased;color:#7c7d82}.side-scroll-bar[data-v-335b6326] .el-scrollbar__wrap{overflow-x:hidden}div.panel-container[data-v-335b6326]{padding-bottom:10px}.no-bottom-margin[data-v-335b6326] .el-tabs__header{margin-bottom:0}.indent-left-margin[data-v-335b6326] .el-tabs__nav{margin-left:20px}.el-collapse-item[data-v-335b6326] ul>li{list-style:none}.widget-collapse[data-v-335b6326]{border-top-width:0}.widget-collapse[data-v-335b6326] .el-collapse-item__header{margin-left:8px;font-style:italic;font-weight:700}.widget-collapse[data-v-335b6326] .el-collapse-item__content{padding-bottom:6px}.widget-collapse[data-v-335b6326] .el-collapse-item__content ul{padding-left:10px;margin:0;margin-block-start:0;margin-block-end:.25em;padding-inline-start:10px}.widget-collapse[data-v-335b6326] .el-collapse-item__content ul:after{content:"";display:block;clear:both}.widget-collapse[data-v-335b6326] .el-collapse-item__content ul .container-widget-item,.widget-collapse[data-v-335b6326] .el-collapse-item__content ul .field-widget-item{display:inline-block;height:32px;line-height:32px;width:98px;float:left;margin:2px 6px 6px 0;cursor:move;white-space:nowrap;text-overflow:ellipsis;overflow:hidden;background:#fff;border:1px solid #e8e9eb;border-radius:4px;padding:0 8px}.widget-collapse[data-v-335b6326] .el-collapse-item__content ul .container-widget-item:hover,.widget-collapse[data-v-335b6326] .el-collapse-item__content ul .field-widget-item:hover{background:#F1F2F3;border-color:#409eff}.widget-collapse[data-v-335b6326] .el-collapse-item__content ul .container-widget-item:hover .color-svg-icon,.widget-collapse[data-v-335b6326] .el-collapse-item__content ul .field-widget-item:hover .color-svg-icon{color:#409eff}.widget-collapse[data-v-335b6326] .el-collapse-item__content ul .drag-handler{position:absolute;top:0;left:160px;background-color:#ddd;border-radius:5px;padding-right:5px;font-size:11px;color:#666}.el-card.ft-card[data-v-335b6326]{border:1px solid #8896B3}.ft-card[data-v-335b6326]{margin-bottom:10px}.ft-card .bottom[data-v-335b6326]{margin-top:10px;line-height:12px}.ft-card .ft-title[data-v-335b6326]{font-size:13px;font-weight:700}.ft-card .right-button[data-v-335b6326]{padding:0;float:right}.ft-card .clear-fix[data-v-335b6326]:before,.ft-card .clear-fix[data-v-335b6326]:after{display:table;content:""}.ft-card .clear-fix[data-v-335b6326]:after{clear:both}.primary-color[data-v-41799baa]{color:#409eff}.background-opacity[data-v-41799baa]{background:rgba(64,158,255,.6)}.form-widget-list .ghost[data-v-41799baa]{content:"";font-size:0;height:3px;box-sizing:border-box;background:#409EFF;border:2px solid #409EFF;outline-width:0;padding:0;overflow:hidden}.el-form-item .el-rate[data-v-41799baa]{margin-top:8px}.el-form-item--medium .el-radio[data-v-41799baa]{line-height:36px!important}.el-form-item--medium .el-rate[data-v-41799baa]{margin-top:8px}.el-form-item--small .el-radio[data-v-41799baa]{line-height:32px!important}.el-form-item--small .el-rate[data-v-41799baa]{margin-top:6px}.el-form-item--mini .el-radio[data-v-41799baa]{line-height:28px!important}.el-form-item--mini .el-rate[data-v-41799baa]{margin-top:4px}.el-card[data-v-41799baa]{margin-top:3px;margin-bottom:3px}input[type=password][data-v-41799baa]::-ms-reveal{display:none}.auto-full-width.el-date-editor.el-input[data-v-41799baa],.auto-full-width.el-date-editor.el-input__inner[data-v-41799baa]{width:100%!important}[data-v-41799baa]::-webkit-scrollbar{width:8px;height:8px}[data-v-41799baa]::-webkit-scrollbar-track{width:8px;background:rgba(16,31,28,.1);-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-41799baa]::-webkit-scrollbar-thumb{background-color:#101f1c59;background-clip:padding-box;min-height:28px;-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-41799baa]::-webkit-scrollbar-thumb:hover{background-color:#101f1cd9}*[data-v-41799baa]{scrollbar-color:#e5e5e5 #f7f7f9;scrollbar-width:thin}.design-time-bottom-margin[data-v-41799baa]{margin-bottom:5px}.field-wrapper[data-v-41799baa]{position:relative}.field-wrapper .field-action[data-v-41799baa]{position:absolute;bottom:0;right:-2px;height:22px;line-height:22px;background:#409EFF;z-index:9}.field-wrapper .field-action i[data-v-41799baa]{font-size:14px;color:#fff;margin:0 5px;cursor:pointer}.field-wrapper .drag-handler[data-v-41799baa]{position:absolute;top:0;left:-1px;height:20px;line-height:20px;z-index:9}.field-wrapper .drag-handler i[data-v-41799baa]{font-size:12px;font-style:normal;color:#fff;margin:4px;cursor:move}.field-wrapper .drag-handler[data-v-41799baa]:hover{background:#409EFF}.field-action[data-v-41799baa] .svg-icon,.drag-handler[data-v-41799baa] .svg-icon{margin-left:.1em;margin-right:.1em}.static-content-item[data-v-41799baa]{min-height:20px;display:flex;align-items:center}.static-content-item[data-v-41799baa] .el-divider--horizontal{margin:0}.el-form-item.selected[data-v-41799baa],.static-content-item.selected[data-v-41799baa]{outline:2px solid #409EFF}.primary-color[data-v-1ba2a127]{color:#409eff}.background-opacity[data-v-1ba2a127]{background:rgba(64,158,255,.6)}.form-widget-list .ghost[data-v-1ba2a127]{content:"";font-size:0;height:3px;box-sizing:border-box;background:#409EFF;border:2px solid #409EFF;outline-width:0;padding:0;overflow:hidden}.el-form-item .el-rate[data-v-1ba2a127]{margin-top:8px}.el-form-item--medium .el-radio[data-v-1ba2a127]{line-height:36px!important}.el-form-item--medium .el-rate[data-v-1ba2a127]{margin-top:8px}.el-form-item--small .el-radio[data-v-1ba2a127]{line-height:32px!important}.el-form-item--small .el-rate[data-v-1ba2a127]{margin-top:6px}.el-form-item--mini .el-radio[data-v-1ba2a127]{line-height:28px!important}.el-form-item--mini .el-rate[data-v-1ba2a127]{margin-top:4px}.el-card[data-v-1ba2a127]{margin-top:3px;margin-bottom:3px}input[type=password][data-v-1ba2a127]::-ms-reveal{display:none}.auto-full-width.el-date-editor.el-input[data-v-1ba2a127],.auto-full-width.el-date-editor.el-input__inner[data-v-1ba2a127]{width:100%!important}[data-v-1ba2a127]::-webkit-scrollbar{width:8px;height:8px}[data-v-1ba2a127]::-webkit-scrollbar-track{width:8px;background:rgba(16,31,28,.1);-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-1ba2a127]::-webkit-scrollbar-thumb{background-color:#101f1c59;background-clip:padding-box;min-height:28px;-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-1ba2a127]::-webkit-scrollbar-thumb:hover{background-color:#101f1cd9}*[data-v-1ba2a127]{scrollbar-color:#e5e5e5 #f7f7f9;scrollbar-width:thin}.primary-color[data-v-150e0c61]{color:#409eff}.background-opacity[data-v-150e0c61]{background:rgba(64,158,255,.6)}.form-widget-list .ghost[data-v-150e0c61]{content:"";font-size:0;height:3px;box-sizing:border-box;background:#409EFF;border:2px solid #409EFF;outline-width:0;padding:0;overflow:hidden}.el-form-item .el-rate[data-v-150e0c61]{margin-top:8px}.el-form-item--medium .el-radio[data-v-150e0c61]{line-height:36px!important}.el-form-item--medium .el-rate[data-v-150e0c61]{margin-top:8px}.el-form-item--small .el-radio[data-v-150e0c61]{line-height:32px!important}.el-form-item--small .el-rate[data-v-150e0c61]{margin-top:6px}.el-form-item--mini .el-radio[data-v-150e0c61]{line-height:28px!important}.el-form-item--mini .el-rate[data-v-150e0c61]{margin-top:4px}.el-card[data-v-150e0c61]{margin-top:3px;margin-bottom:3px}input[type=password][data-v-150e0c61]::-ms-reveal{display:none}.auto-full-width.el-date-editor.el-input[data-v-150e0c61],.auto-full-width.el-date-editor.el-input__inner[data-v-150e0c61]{width:100%!important}[data-v-150e0c61]::-webkit-scrollbar{width:8px;height:8px}[data-v-150e0c61]::-webkit-scrollbar-track{width:8px;background:rgba(16,31,28,.1);-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-150e0c61]::-webkit-scrollbar-thumb{background-color:#101f1c59;background-clip:padding-box;min-height:28px;-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-150e0c61]::-webkit-scrollbar-thumb:hover{background-color:#101f1cd9}*[data-v-150e0c61]{scrollbar-color:#e5e5e5 #f7f7f9;scrollbar-width:thin}.design-time-bottom-margin[data-v-150e0c61]{margin-bottom:5px}.field-wrapper[data-v-150e0c61]{position:relative}.field-wrapper .field-action[data-v-150e0c61]{position:absolute;bottom:0;right:-2px;height:22px;line-height:22px;background:#409EFF;z-index:9}.field-wrapper .field-action i[data-v-150e0c61]{font-size:14px;color:#fff;margin:0 3px;cursor:pointer}.field-wrapper .drag-handler[data-v-150e0c61]{position:absolute;top:0;left:-1px;height:20px;line-height:20px;z-index:9}.field-wrapper .drag-handler i[data-v-150e0c61]{font-size:12px;font-style:normal;color:#fff;margin:4px;cursor:move}.field-wrapper .drag-handler[data-v-150e0c61]:hover{background:#409EFF}.field-action[data-v-150e0c61] .svg-icon,.drag-handler[data-v-150e0c61] .svg-icon{margin-left:0;margin-right:0}.el-form-item[data-v-150e0c61]{position:relative}.el-form-item[data-v-150e0c61] .el-form-item__label{white-space:nowrap;text-overflow:ellipsis}.el-form-item span.custom-label i[data-v-150e0c61]{margin:0 3px}.el-form-item[data-v-150e0c61] .hide-spin-button input::-webkit-outer-spin-button,.el-form-item[data-v-150e0c61] .hide-spin-button input::-webkit-inner-spin-button{-webkit-appearance:none!important}.el-form-item[data-v-150e0c61] .hide-spin-button input[type=number]{-moz-appearance:textfield}.required[data-v-150e0c61] .el-form-item__label:before{content:"*";color:#f56c6c;margin-right:4px}.static-content-item[data-v-150e0c61]{min-height:20px;display:flex;align-items:center}.static-content-item[data-v-150e0c61] .el-divider--horizontal{margin:0}.el-form-item.selected[data-v-150e0c61],.static-content-item.selected[data-v-150e0c61]{outline:2px solid #409EFF}[data-v-150e0c61] .label-left-align .el-form-item__label{text-align:left;justify-content:flex-start!important}[data-v-150e0c61] .label-center-align .el-form-item__label{text-align:center;justify-content:center!important}[data-v-150e0c61] .label-right-align .el-form-item__label{text-align:right;justify-content:flex-end!important}.primary-color[data-v-ec070d7c]{color:#409eff}.background-opacity[data-v-ec070d7c]{background:rgba(64,158,255,.6)}.form-widget-list .ghost[data-v-ec070d7c]{content:"";font-size:0;height:3px;box-sizing:border-box;background:#409EFF;border:2px solid #409EFF;outline-width:0;padding:0;overflow:hidden}.el-form-item .el-rate[data-v-ec070d7c]{margin-top:8px}.el-form-item--medium .el-radio[data-v-ec070d7c]{line-height:36px!important}.el-form-item--medium .el-rate[data-v-ec070d7c]{margin-top:8px}.el-form-item--small .el-radio[data-v-ec070d7c]{line-height:32px!important}.el-form-item--small .el-rate[data-v-ec070d7c]{margin-top:6px}.el-form-item--mini .el-radio[data-v-ec070d7c]{line-height:28px!important}.el-form-item--mini .el-rate[data-v-ec070d7c]{margin-top:4px}.el-card[data-v-ec070d7c]{margin-top:3px;margin-bottom:3px}input[type=password][data-v-ec070d7c]::-ms-reveal{display:none}.auto-full-width.el-date-editor.el-input[data-v-ec070d7c],.auto-full-width.el-date-editor.el-input__inner[data-v-ec070d7c]{width:100%!important}[data-v-ec070d7c]::-webkit-scrollbar{width:8px;height:8px}[data-v-ec070d7c]::-webkit-scrollbar-track{width:8px;background:rgba(16,31,28,.1);-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-ec070d7c]::-webkit-scrollbar-thumb{background-color:#101f1c59;background-clip:padding-box;min-height:28px;-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-ec070d7c]::-webkit-scrollbar-thumb:hover{background-color:#101f1cd9}*[data-v-ec070d7c]{scrollbar-color:#e5e5e5 #f7f7f9;scrollbar-width:thin}.full-width-input[data-v-ec070d7c],.full-width-input[data-v-ec070d7c] .el-cascader{width:100%!important}.primary-color[data-v-716b0a6b]{color:#409eff}.background-opacity[data-v-716b0a6b]{background:rgba(64,158,255,.6)}.form-widget-list .ghost[data-v-716b0a6b]{content:"";font-size:0;height:3px;box-sizing:border-box;background:#409EFF;border:2px solid #409EFF;outline-width:0;padding:0;overflow:hidden}.el-form-item .el-rate[data-v-716b0a6b]{margin-top:8px}.el-form-item--medium .el-radio[data-v-716b0a6b]{line-height:36px!important}.el-form-item--medium .el-rate[data-v-716b0a6b]{margin-top:8px}.el-form-item--small .el-radio[data-v-716b0a6b]{line-height:32px!important}.el-form-item--small .el-rate[data-v-716b0a6b]{margin-top:6px}.el-form-item--mini .el-radio[data-v-716b0a6b]{line-height:28px!important}.el-form-item--mini .el-rate[data-v-716b0a6b]{margin-top:4px}.el-card[data-v-716b0a6b]{margin-top:3px;margin-bottom:3px}input[type=password][data-v-716b0a6b]::-ms-reveal{display:none}.auto-full-width.el-date-editor.el-input[data-v-716b0a6b],.auto-full-width.el-date-editor.el-input__inner[data-v-716b0a6b]{width:100%!important}[data-v-716b0a6b]::-webkit-scrollbar{width:8px;height:8px}[data-v-716b0a6b]::-webkit-scrollbar-track{width:8px;background:rgba(16,31,28,.1);-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-716b0a6b]::-webkit-scrollbar-thumb{background-color:#101f1c59;background-clip:padding-box;min-height:28px;-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-716b0a6b]::-webkit-scrollbar-thumb:hover{background-color:#101f1cd9}*[data-v-716b0a6b]{scrollbar-color:#e5e5e5 #f7f7f9;scrollbar-width:thin}.primary-color[data-v-8d04bd98]{color:#409eff}.background-opacity[data-v-8d04bd98]{background:rgba(64,158,255,.6)}.form-widget-list .ghost[data-v-8d04bd98]{content:"";font-size:0;height:3px;box-sizing:border-box;background:#409EFF;border:2px solid #409EFF;outline-width:0;padding:0;overflow:hidden}.el-form-item .el-rate[data-v-8d04bd98]{margin-top:8px}.el-form-item--medium .el-radio[data-v-8d04bd98]{line-height:36px!important}.el-form-item--medium .el-rate[data-v-8d04bd98]{margin-top:8px}.el-form-item--small .el-radio[data-v-8d04bd98]{line-height:32px!important}.el-form-item--small .el-rate[data-v-8d04bd98]{margin-top:6px}.el-form-item--mini .el-radio[data-v-8d04bd98]{line-height:28px!important}.el-form-item--mini .el-rate[data-v-8d04bd98]{margin-top:4px}.el-card[data-v-8d04bd98]{margin-top:3px;margin-bottom:3px}input[type=password][data-v-8d04bd98]::-ms-reveal{display:none}.auto-full-width.el-date-editor.el-input[data-v-8d04bd98],.auto-full-width.el-date-editor.el-input__inner[data-v-8d04bd98]{width:100%!important}[data-v-8d04bd98]::-webkit-scrollbar{width:8px;height:8px}[data-v-8d04bd98]::-webkit-scrollbar-track{width:8px;background:rgba(16,31,28,.1);-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-8d04bd98]::-webkit-scrollbar-thumb{background-color:#101f1c59;background-clip:padding-box;min-height:28px;-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-8d04bd98]::-webkit-scrollbar-thumb:hover{background-color:#101f1cd9}*[data-v-8d04bd98]{scrollbar-color:#e5e5e5 #f7f7f9;scrollbar-width:thin}.full-width-input[data-v-8d04bd98]{width:100%!important}.primary-color[data-v-21300a07]{color:#409eff}.background-opacity[data-v-21300a07]{background:rgba(64,158,255,.6)}.form-widget-list .ghost[data-v-21300a07]{content:"";font-size:0;height:3px;box-sizing:border-box;background:#409EFF;border:2px solid #409EFF;outline-width:0;padding:0;overflow:hidden}.el-form-item .el-rate[data-v-21300a07]{margin-top:8px}.el-form-item--medium .el-radio[data-v-21300a07]{line-height:36px!important}.el-form-item--medium .el-rate[data-v-21300a07]{margin-top:8px}.el-form-item--small .el-radio[data-v-21300a07]{line-height:32px!important}.el-form-item--small .el-rate[data-v-21300a07]{margin-top:6px}.el-form-item--mini .el-radio[data-v-21300a07]{line-height:28px!important}.el-form-item--mini .el-rate[data-v-21300a07]{margin-top:4px}.el-card[data-v-21300a07]{margin-top:3px;margin-bottom:3px}input[type=password][data-v-21300a07]::-ms-reveal{display:none}.auto-full-width.el-date-editor.el-input[data-v-21300a07],.auto-full-width.el-date-editor.el-input__inner[data-v-21300a07]{width:100%!important}[data-v-21300a07]::-webkit-scrollbar{width:8px;height:8px}[data-v-21300a07]::-webkit-scrollbar-track{width:8px;background:rgba(16,31,28,.1);-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-21300a07]::-webkit-scrollbar-thumb{background-color:#101f1c59;background-clip:padding-box;min-height:28px;-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-21300a07]::-webkit-scrollbar-thumb:hover{background-color:#101f1cd9}*[data-v-21300a07]{scrollbar-color:#e5e5e5 #f7f7f9;scrollbar-width:thin}.full-width-input[data-v-21300a07]{width:100%!important}.auto-full-width[data-v-21300a07]{width:100%}.auto-full-width[data-v-21300a07] .el-range-editor{width:100%!important}.primary-color[data-v-75b85548]{color:#409eff}.background-opacity[data-v-75b85548]{background:rgba(64,158,255,.6)}.form-widget-list .ghost[data-v-75b85548]{content:"";font-size:0;height:3px;box-sizing:border-box;background:#409EFF;border:2px solid #409EFF;outline-width:0;padding:0;overflow:hidden}.el-form-item .el-rate[data-v-75b85548]{margin-top:8px}.el-form-item--medium .el-radio[data-v-75b85548]{line-height:36px!important}.el-form-item--medium .el-rate[data-v-75b85548]{margin-top:8px}.el-form-item--small .el-radio[data-v-75b85548]{line-height:32px!important}.el-form-item--small .el-rate[data-v-75b85548]{margin-top:6px}.el-form-item--mini .el-radio[data-v-75b85548]{line-height:28px!important}.el-form-item--mini .el-rate[data-v-75b85548]{margin-top:4px}.el-card[data-v-75b85548]{margin-top:3px;margin-bottom:3px}input[type=password][data-v-75b85548]::-ms-reveal{display:none}.auto-full-width.el-date-editor.el-input[data-v-75b85548],.auto-full-width.el-date-editor.el-input__inner[data-v-75b85548]{width:100%!important}[data-v-75b85548]::-webkit-scrollbar{width:8px;height:8px}[data-v-75b85548]::-webkit-scrollbar-track{width:8px;background:rgba(16,31,28,.1);-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-75b85548]::-webkit-scrollbar-thumb{background-color:#101f1c59;background-clip:padding-box;min-height:28px;-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-75b85548]::-webkit-scrollbar-thumb:hover{background-color:#101f1cd9}*[data-v-75b85548]{scrollbar-color:#e5e5e5 #f7f7f9;scrollbar-width:thin}.full-width-input[data-v-75b85548]{width:100%!important}.primary-color[data-v-09a1b973]{color:#409eff}.background-opacity[data-v-09a1b973]{background:rgba(64,158,255,.6)}.form-widget-list .ghost[data-v-09a1b973]{content:"";font-size:0;height:3px;box-sizing:border-box;background:#409EFF;border:2px solid #409EFF;outline-width:0;padding:0;overflow:hidden}.el-form-item .el-rate[data-v-09a1b973]{margin-top:8px}.el-form-item--medium .el-radio[data-v-09a1b973]{line-height:36px!important}.el-form-item--medium .el-rate[data-v-09a1b973]{margin-top:8px}.el-form-item--small .el-radio[data-v-09a1b973]{line-height:32px!important}.el-form-item--small .el-rate[data-v-09a1b973]{margin-top:6px}.el-form-item--mini .el-radio[data-v-09a1b973]{line-height:28px!important}.el-form-item--mini .el-rate[data-v-09a1b973]{margin-top:4px}.el-card[data-v-09a1b973]{margin-top:3px;margin-bottom:3px}input[type=password][data-v-09a1b973]::-ms-reveal{display:none}.auto-full-width.el-date-editor.el-input[data-v-09a1b973],.auto-full-width.el-date-editor.el-input__inner[data-v-09a1b973]{width:100%!important}[data-v-09a1b973]::-webkit-scrollbar{width:8px;height:8px}[data-v-09a1b973]::-webkit-scrollbar-track{width:8px;background:rgba(16,31,28,.1);-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-09a1b973]::-webkit-scrollbar-thumb{background-color:#101f1c59;background-clip:padding-box;min-height:28px;-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-09a1b973]::-webkit-scrollbar-thumb:hover{background-color:#101f1cd9}*[data-v-09a1b973]{scrollbar-color:#e5e5e5 #f7f7f9;scrollbar-width:thin}.primary-color[data-v-b6b1e8a8]{color:#409eff}.background-opacity[data-v-b6b1e8a8]{background:rgba(64,158,255,.6)}.form-widget-list .ghost[data-v-b6b1e8a8]{content:"";font-size:0;height:3px;box-sizing:border-box;background:#409EFF;border:2px solid #409EFF;outline-width:0;padding:0;overflow:hidden}.el-form-item .el-rate[data-v-b6b1e8a8]{margin-top:8px}.el-form-item--medium .el-radio[data-v-b6b1e8a8]{line-height:36px!important}.el-form-item--medium .el-rate[data-v-b6b1e8a8]{margin-top:8px}.el-form-item--small .el-radio[data-v-b6b1e8a8]{line-height:32px!important}.el-form-item--small .el-rate[data-v-b6b1e8a8]{margin-top:6px}.el-form-item--mini .el-radio[data-v-b6b1e8a8]{line-height:28px!important}.el-form-item--mini .el-rate[data-v-b6b1e8a8]{margin-top:4px}.el-card[data-v-b6b1e8a8]{margin-top:3px;margin-bottom:3px}input[type=password][data-v-b6b1e8a8]::-ms-reveal{display:none}.auto-full-width.el-date-editor.el-input[data-v-b6b1e8a8],.auto-full-width.el-date-editor.el-input__inner[data-v-b6b1e8a8]{width:100%!important}[data-v-b6b1e8a8]::-webkit-scrollbar{width:8px;height:8px}[data-v-b6b1e8a8]::-webkit-scrollbar-track{width:8px;background:rgba(16,31,28,.1);-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-b6b1e8a8]::-webkit-scrollbar-thumb{background-color:#101f1c59;background-clip:padding-box;min-height:28px;-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-b6b1e8a8]::-webkit-scrollbar-thumb:hover{background-color:#101f1cd9}*[data-v-b6b1e8a8]{scrollbar-color:#e5e5e5 #f7f7f9;scrollbar-width:thin}.full-width-input[data-v-b6b1e8a8]{width:100%!important}.dynamicPseudoAfter[data-v-b6b1e8a8] .el-upload.el-upload--text{color:#409eff;font-size:12px}.dynamicPseudoAfter[data-v-b6b1e8a8] .el-upload.el-upload--text .el-icon-plus:after{content:var(--select-file-action)}.hideUploadDiv[data-v-b6b1e8a8] div.el-upload--picture-card,.hideUploadDiv[data-v-b6b1e8a8] div.el-upload--text,.hideUploadDiv[data-v-b6b1e8a8] div.el-upload__tip{display:none}.upload-file-list[data-v-b6b1e8a8]{font-size:12px}.upload-file-list .file-action[data-v-b6b1e8a8]{color:#409eff;margin-left:5px;margin-right:5px;cursor:pointer}.primary-color[data-v-3d941b4e]{color:#409eff}.background-opacity[data-v-3d941b4e]{background:rgba(64,158,255,.6)}.form-widget-list .ghost[data-v-3d941b4e]{content:"";font-size:0;height:3px;box-sizing:border-box;background:#409EFF;border:2px solid #409EFF;outline-width:0;padding:0;overflow:hidden}.el-form-item .el-rate[data-v-3d941b4e]{margin-top:8px}.el-form-item--medium .el-radio[data-v-3d941b4e]{line-height:36px!important}.el-form-item--medium .el-rate[data-v-3d941b4e]{margin-top:8px}.el-form-item--small .el-radio[data-v-3d941b4e]{line-height:32px!important}.el-form-item--small .el-rate[data-v-3d941b4e]{margin-top:6px}.el-form-item--mini .el-radio[data-v-3d941b4e]{line-height:28px!important}.el-form-item--mini .el-rate[data-v-3d941b4e]{margin-top:4px}.el-card[data-v-3d941b4e]{margin-top:3px;margin-bottom:3px}input[type=password][data-v-3d941b4e]::-ms-reveal{display:none}.auto-full-width.el-date-editor.el-input[data-v-3d941b4e],.auto-full-width.el-date-editor.el-input__inner[data-v-3d941b4e]{width:100%!important}[data-v-3d941b4e]::-webkit-scrollbar{width:8px;height:8px}[data-v-3d941b4e]::-webkit-scrollbar-track{width:8px;background:rgba(16,31,28,.1);-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-3d941b4e]::-webkit-scrollbar-thumb{background-color:#101f1c59;background-clip:padding-box;min-height:28px;-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-3d941b4e]::-webkit-scrollbar-thumb:hover{background-color:#101f1cd9}*[data-v-3d941b4e]{scrollbar-color:#e5e5e5 #f7f7f9;scrollbar-width:thin}.primary-color[data-v-0aad1a31]{color:#409eff}.background-opacity[data-v-0aad1a31]{background:rgba(64,158,255,.6)}.form-widget-list .ghost[data-v-0aad1a31]{content:"";font-size:0;height:3px;box-sizing:border-box;background:#409EFF;border:2px solid #409EFF;outline-width:0;padding:0;overflow:hidden}.el-form-item .el-rate[data-v-0aad1a31]{margin-top:8px}.el-form-item--medium .el-radio[data-v-0aad1a31]{line-height:36px!important}.el-form-item--medium .el-rate[data-v-0aad1a31]{margin-top:8px}.el-form-item--small .el-radio[data-v-0aad1a31]{line-height:32px!important}.el-form-item--small .el-rate[data-v-0aad1a31]{margin-top:6px}.el-form-item--mini .el-radio[data-v-0aad1a31]{line-height:28px!important}.el-form-item--mini .el-rate[data-v-0aad1a31]{margin-top:4px}.el-card[data-v-0aad1a31]{margin-top:3px;margin-bottom:3px}input[type=password][data-v-0aad1a31]::-ms-reveal{display:none}.auto-full-width.el-date-editor.el-input[data-v-0aad1a31],.auto-full-width.el-date-editor.el-input__inner[data-v-0aad1a31]{width:100%!important}[data-v-0aad1a31]::-webkit-scrollbar{width:8px;height:8px}[data-v-0aad1a31]::-webkit-scrollbar-track{width:8px;background:rgba(16,31,28,.1);-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-0aad1a31]::-webkit-scrollbar-thumb{background-color:#101f1c59;background-clip:padding-box;min-height:28px;-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-0aad1a31]::-webkit-scrollbar-thumb:hover{background-color:#101f1cd9}*[data-v-0aad1a31]{scrollbar-color:#e5e5e5 #f7f7f9;scrollbar-width:thin}.primary-color[data-v-0b9bc82f]{color:#409eff}.background-opacity[data-v-0b9bc82f]{background:rgba(64,158,255,.6)}.form-widget-list .ghost[data-v-0b9bc82f]{content:"";font-size:0;height:3px;box-sizing:border-box;background:#409EFF;border:2px solid #409EFF;outline-width:0;padding:0;overflow:hidden}.el-form-item .el-rate[data-v-0b9bc82f]{margin-top:8px}.el-form-item--medium .el-radio[data-v-0b9bc82f]{line-height:36px!important}.el-form-item--medium .el-rate[data-v-0b9bc82f]{margin-top:8px}.el-form-item--small .el-radio[data-v-0b9bc82f]{line-height:32px!important}.el-form-item--small .el-rate[data-v-0b9bc82f]{margin-top:6px}.el-form-item--mini .el-radio[data-v-0b9bc82f]{line-height:28px!important}.el-form-item--mini .el-rate[data-v-0b9bc82f]{margin-top:4px}.el-card[data-v-0b9bc82f]{margin-top:3px;margin-bottom:3px}input[type=password][data-v-0b9bc82f]::-ms-reveal{display:none}.auto-full-width.el-date-editor.el-input[data-v-0b9bc82f],.auto-full-width.el-date-editor.el-input__inner[data-v-0b9bc82f]{width:100%!important}[data-v-0b9bc82f]::-webkit-scrollbar{width:8px;height:8px}[data-v-0b9bc82f]::-webkit-scrollbar-track{width:8px;background:rgba(16,31,28,.1);-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-0b9bc82f]::-webkit-scrollbar-thumb{background-color:#101f1c59;background-clip:padding-box;min-height:28px;-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-0b9bc82f]::-webkit-scrollbar-thumb:hover{background-color:#101f1cd9}*[data-v-0b9bc82f]{scrollbar-color:#e5e5e5 #f7f7f9;scrollbar-width:thin}.full-width-input[data-v-0b9bc82f]{width:100%!important}.primary-color[data-v-3393010d]{color:#409eff}.background-opacity[data-v-3393010d]{background:rgba(64,158,255,.6)}.form-widget-list .ghost[data-v-3393010d]{content:"";font-size:0;height:3px;box-sizing:border-box;background:#409EFF;border:2px solid #409EFF;outline-width:0;padding:0;overflow:hidden}.el-form-item .el-rate[data-v-3393010d]{margin-top:8px}.el-form-item--medium .el-radio[data-v-3393010d]{line-height:36px!important}.el-form-item--medium .el-rate[data-v-3393010d]{margin-top:8px}.el-form-item--small .el-radio[data-v-3393010d]{line-height:32px!important}.el-form-item--small .el-rate[data-v-3393010d]{margin-top:6px}.el-form-item--mini .el-radio[data-v-3393010d]{line-height:28px!important}.el-form-item--mini .el-rate[data-v-3393010d]{margin-top:4px}.el-card[data-v-3393010d]{margin-top:3px;margin-bottom:3px}input[type=password][data-v-3393010d]::-ms-reveal{display:none}.auto-full-width.el-date-editor.el-input[data-v-3393010d],.auto-full-width.el-date-editor.el-input__inner[data-v-3393010d]{width:100%!important}[data-v-3393010d]::-webkit-scrollbar{width:8px;height:8px}[data-v-3393010d]::-webkit-scrollbar-track{width:8px;background:rgba(16,31,28,.1);-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-3393010d]::-webkit-scrollbar-thumb{background-color:#101f1c59;background-clip:padding-box;min-height:28px;-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-3393010d]::-webkit-scrollbar-thumb:hover{background-color:#101f1cd9}*[data-v-3393010d]{scrollbar-color:#e5e5e5 #f7f7f9;scrollbar-width:thin}.full-width-input[data-v-3393010d]{width:100%!important}.hideUploadDiv[data-v-3393010d] div.el-upload--picture-card,.hideUploadDiv[data-v-3393010d] div.el-upload--text,.hideUploadDiv[data-v-3393010d] div.el-upload__tip{display:none}.uploader-icon[data-v-3393010d]{height:100%;display:flex;color:#8c939d;font-size:28px;justify-content:center;align-items:center}.primary-color[data-v-253adc5e]{color:#409eff}.background-opacity[data-v-253adc5e]{background:rgba(64,158,255,.6)}.form-widget-list .ghost[data-v-253adc5e]{content:"";font-size:0;height:3px;box-sizing:border-box;background:#409EFF;border:2px solid #409EFF;outline-width:0;padding:0;overflow:hidden}.el-form-item .el-rate[data-v-253adc5e]{margin-top:8px}.el-form-item--medium .el-radio[data-v-253adc5e]{line-height:36px!important}.el-form-item--medium .el-rate[data-v-253adc5e]{margin-top:8px}.el-form-item--small .el-radio[data-v-253adc5e]{line-height:32px!important}.el-form-item--small .el-rate[data-v-253adc5e]{margin-top:6px}.el-form-item--mini .el-radio[data-v-253adc5e]{line-height:28px!important}.el-form-item--mini .el-rate[data-v-253adc5e]{margin-top:4px}.el-card[data-v-253adc5e]{margin-top:3px;margin-bottom:3px}input[type=password][data-v-253adc5e]::-ms-reveal{display:none}.auto-full-width.el-date-editor.el-input[data-v-253adc5e],.auto-full-width.el-date-editor.el-input__inner[data-v-253adc5e]{width:100%!important}[data-v-253adc5e]::-webkit-scrollbar{width:8px;height:8px}[data-v-253adc5e]::-webkit-scrollbar-track{width:8px;background:rgba(16,31,28,.1);-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-253adc5e]::-webkit-scrollbar-thumb{background-color:#101f1c59;background-clip:padding-box;min-height:28px;-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-253adc5e]::-webkit-scrollbar-thumb:hover{background-color:#101f1cd9}*[data-v-253adc5e]{scrollbar-color:#e5e5e5 #f7f7f9;scrollbar-width:thin}.radio-group-block[data-v-253adc5e]{display:block!important}.primary-color[data-v-409c0e8b]{color:#409eff}.background-opacity[data-v-409c0e8b]{background:rgba(64,158,255,.6)}.form-widget-list .ghost[data-v-409c0e8b]{content:"";font-size:0;height:3px;box-sizing:border-box;background:#409EFF;border:2px solid #409EFF;outline-width:0;padding:0;overflow:hidden}.el-form-item .el-rate[data-v-409c0e8b]{margin-top:8px}.el-form-item--medium .el-radio[data-v-409c0e8b]{line-height:36px!important}.el-form-item--medium .el-rate[data-v-409c0e8b]{margin-top:8px}.el-form-item--small .el-radio[data-v-409c0e8b]{line-height:32px!important}.el-form-item--small .el-rate[data-v-409c0e8b]{margin-top:6px}.el-form-item--mini .el-radio[data-v-409c0e8b]{line-height:28px!important}.el-form-item--mini .el-rate[data-v-409c0e8b]{margin-top:4px}.el-card[data-v-409c0e8b]{margin-top:3px;margin-bottom:3px}input[type=password][data-v-409c0e8b]::-ms-reveal{display:none}.auto-full-width.el-date-editor.el-input[data-v-409c0e8b],.auto-full-width.el-date-editor.el-input__inner[data-v-409c0e8b]{width:100%!important}[data-v-409c0e8b]::-webkit-scrollbar{width:8px;height:8px}[data-v-409c0e8b]::-webkit-scrollbar-track{width:8px;background:rgba(16,31,28,.1);-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-409c0e8b]::-webkit-scrollbar-thumb{background-color:#101f1c59;background-clip:padding-box;min-height:28px;-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-409c0e8b]::-webkit-scrollbar-thumb:hover{background-color:#101f1cd9}*[data-v-409c0e8b]{scrollbar-color:#e5e5e5 #f7f7f9;scrollbar-width:thin}.full-width-input[data-v-409c0e8b]{width:100%!important}/*! +* Quill Editor v1.3.7 +* https://quilljs.com/ +* Copyright (c) 2014, Jason Chen +* Copyright (c) 2013, salesforce.com +*//*! + * Quill Editor v1.3.7 + * https://quilljs.com/ + * Copyright (c) 2014, Jason Chen + * Copyright (c) 2013, salesforce.com + */.ql-container{box-sizing:border-box;font-family:Helvetica,Arial,sans-serif;font-size:13px;height:100%;margin:0;position:relative}.ql-container.ql-disabled .ql-tooltip{visibility:hidden}.ql-container.ql-disabled .ql-editor ul[data-checked]>li:before{pointer-events:none}.ql-clipboard{left:-100000px;height:1px;overflow-y:hidden;position:absolute;top:50%}.ql-clipboard p{margin:0;padding:0}.ql-editor{box-sizing:border-box;line-height:1.42;height:100%;outline:none;overflow-y:auto;padding:12px 15px;tab-size:4;-moz-tab-size:4;text-align:left;white-space:pre-wrap;word-wrap:break-word}.ql-editor>*{cursor:text}.ql-editor p,.ql-editor ol,.ql-editor ul,.ql-editor pre,.ql-editor blockquote,.ql-editor h1,.ql-editor h2,.ql-editor h3,.ql-editor h4,.ql-editor h5,.ql-editor h6{margin:0;padding:0;counter-reset:list-1 list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9}.ql-editor ol,.ql-editor ul{padding-left:1.5em}.ql-editor ol>li,.ql-editor ul>li{list-style-type:none}.ql-editor ul>li:before{content:"\2022"}.ql-editor ul[data-checked=true],.ql-editor ul[data-checked=false]{pointer-events:none}.ql-editor ul[data-checked=true]>li *,.ql-editor ul[data-checked=false]>li *{pointer-events:all}.ql-editor ul[data-checked=true]>li:before,.ql-editor ul[data-checked=false]>li:before{color:#777;cursor:pointer;pointer-events:all}.ql-editor ul[data-checked=true]>li:before{content:"\2611"}.ql-editor ul[data-checked=false]>li:before{content:"\2610"}.ql-editor li:before{display:inline-block;white-space:nowrap;width:1.2em}.ql-editor li:not(.ql-direction-rtl):before{margin-left:-1.5em;margin-right:.3em;text-align:right}.ql-editor li.ql-direction-rtl:before{margin-left:.3em;margin-right:-1.5em}.ql-editor ol li:not(.ql-direction-rtl),.ql-editor ul li:not(.ql-direction-rtl){padding-left:1.5em}.ql-editor ol li.ql-direction-rtl,.ql-editor ul li.ql-direction-rtl{padding-right:1.5em}.ql-editor ol li{counter-reset:list-1 list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9;counter-increment:list-0}.ql-editor ol li:before{content:counter(list-0,decimal) ". "}.ql-editor ol li.ql-indent-1{counter-increment:list-1}.ql-editor ol li.ql-indent-1:before{content:counter(list-1,lower-alpha) ". "}.ql-editor ol li.ql-indent-1{counter-reset:list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9}.ql-editor ol li.ql-indent-2{counter-increment:list-2}.ql-editor ol li.ql-indent-2:before{content:counter(list-2,lower-roman) ". "}.ql-editor ol li.ql-indent-2{counter-reset:list-3 list-4 list-5 list-6 list-7 list-8 list-9}.ql-editor ol li.ql-indent-3{counter-increment:list-3}.ql-editor ol li.ql-indent-3:before{content:counter(list-3,decimal) ". "}.ql-editor ol li.ql-indent-3{counter-reset:list-4 list-5 list-6 list-7 list-8 list-9}.ql-editor ol li.ql-indent-4{counter-increment:list-4}.ql-editor ol li.ql-indent-4:before{content:counter(list-4,lower-alpha) ". "}.ql-editor ol li.ql-indent-4{counter-reset:list-5 list-6 list-7 list-8 list-9}.ql-editor ol li.ql-indent-5{counter-increment:list-5}.ql-editor ol li.ql-indent-5:before{content:counter(list-5,lower-roman) ". "}.ql-editor ol li.ql-indent-5{counter-reset:list-6 list-7 list-8 list-9}.ql-editor ol li.ql-indent-6{counter-increment:list-6}.ql-editor ol li.ql-indent-6:before{content:counter(list-6,decimal) ". "}.ql-editor ol li.ql-indent-6{counter-reset:list-7 list-8 list-9}.ql-editor ol li.ql-indent-7{counter-increment:list-7}.ql-editor ol li.ql-indent-7:before{content:counter(list-7,lower-alpha) ". "}.ql-editor ol li.ql-indent-7{counter-reset:list-8 list-9}.ql-editor ol li.ql-indent-8{counter-increment:list-8}.ql-editor ol li.ql-indent-8:before{content:counter(list-8,lower-roman) ". "}.ql-editor ol li.ql-indent-8{counter-reset:list-9}.ql-editor ol li.ql-indent-9{counter-increment:list-9}.ql-editor ol li.ql-indent-9:before{content:counter(list-9,decimal) ". "}.ql-editor .ql-indent-1:not(.ql-direction-rtl){padding-left:3em}.ql-editor li.ql-indent-1:not(.ql-direction-rtl){padding-left:4.5em}.ql-editor .ql-indent-1.ql-direction-rtl.ql-align-right{padding-right:3em}.ql-editor li.ql-indent-1.ql-direction-rtl.ql-align-right{padding-right:4.5em}.ql-editor .ql-indent-2:not(.ql-direction-rtl){padding-left:6em}.ql-editor li.ql-indent-2:not(.ql-direction-rtl){padding-left:7.5em}.ql-editor .ql-indent-2.ql-direction-rtl.ql-align-right{padding-right:6em}.ql-editor li.ql-indent-2.ql-direction-rtl.ql-align-right{padding-right:7.5em}.ql-editor .ql-indent-3:not(.ql-direction-rtl){padding-left:9em}.ql-editor li.ql-indent-3:not(.ql-direction-rtl){padding-left:10.5em}.ql-editor .ql-indent-3.ql-direction-rtl.ql-align-right{padding-right:9em}.ql-editor li.ql-indent-3.ql-direction-rtl.ql-align-right{padding-right:10.5em}.ql-editor .ql-indent-4:not(.ql-direction-rtl){padding-left:12em}.ql-editor li.ql-indent-4:not(.ql-direction-rtl){padding-left:13.5em}.ql-editor .ql-indent-4.ql-direction-rtl.ql-align-right{padding-right:12em}.ql-editor li.ql-indent-4.ql-direction-rtl.ql-align-right{padding-right:13.5em}.ql-editor .ql-indent-5:not(.ql-direction-rtl){padding-left:15em}.ql-editor li.ql-indent-5:not(.ql-direction-rtl){padding-left:16.5em}.ql-editor .ql-indent-5.ql-direction-rtl.ql-align-right{padding-right:15em}.ql-editor li.ql-indent-5.ql-direction-rtl.ql-align-right{padding-right:16.5em}.ql-editor .ql-indent-6:not(.ql-direction-rtl){padding-left:18em}.ql-editor li.ql-indent-6:not(.ql-direction-rtl){padding-left:19.5em}.ql-editor .ql-indent-6.ql-direction-rtl.ql-align-right{padding-right:18em}.ql-editor li.ql-indent-6.ql-direction-rtl.ql-align-right{padding-right:19.5em}.ql-editor .ql-indent-7:not(.ql-direction-rtl){padding-left:21em}.ql-editor li.ql-indent-7:not(.ql-direction-rtl){padding-left:22.5em}.ql-editor .ql-indent-7.ql-direction-rtl.ql-align-right{padding-right:21em}.ql-editor li.ql-indent-7.ql-direction-rtl.ql-align-right{padding-right:22.5em}.ql-editor .ql-indent-8:not(.ql-direction-rtl){padding-left:24em}.ql-editor li.ql-indent-8:not(.ql-direction-rtl){padding-left:25.5em}.ql-editor .ql-indent-8.ql-direction-rtl.ql-align-right{padding-right:24em}.ql-editor li.ql-indent-8.ql-direction-rtl.ql-align-right{padding-right:25.5em}.ql-editor .ql-indent-9:not(.ql-direction-rtl){padding-left:27em}.ql-editor li.ql-indent-9:not(.ql-direction-rtl){padding-left:28.5em}.ql-editor .ql-indent-9.ql-direction-rtl.ql-align-right{padding-right:27em}.ql-editor li.ql-indent-9.ql-direction-rtl.ql-align-right{padding-right:28.5em}.ql-editor .ql-video{display:block;max-width:100%}.ql-editor .ql-video.ql-align-center{margin:0 auto}.ql-editor .ql-video.ql-align-right{margin:0 0 0 auto}.ql-editor .ql-bg-black{background-color:#000}.ql-editor .ql-bg-red{background-color:#e60000}.ql-editor .ql-bg-orange{background-color:#f90}.ql-editor .ql-bg-yellow{background-color:#ff0}.ql-editor .ql-bg-green{background-color:#008a00}.ql-editor .ql-bg-blue{background-color:#06c}.ql-editor .ql-bg-purple{background-color:#93f}.ql-editor .ql-color-white{color:#fff}.ql-editor .ql-color-red{color:#e60000}.ql-editor .ql-color-orange{color:#f90}.ql-editor .ql-color-yellow{color:#ff0}.ql-editor .ql-color-green{color:#008a00}.ql-editor .ql-color-blue{color:#06c}.ql-editor .ql-color-purple{color:#93f}.ql-editor .ql-font-serif{font-family:Georgia,Times New Roman,serif}.ql-editor .ql-font-monospace{font-family:Monaco,Courier New,monospace}.ql-editor .ql-size-small{font-size:.75em}.ql-editor .ql-size-large{font-size:1.5em}.ql-editor .ql-size-huge{font-size:2.5em}.ql-editor .ql-direction-rtl{direction:rtl;text-align:inherit}.ql-editor .ql-align-center{text-align:center}.ql-editor .ql-align-justify{text-align:justify}.ql-editor .ql-align-right{text-align:right}.ql-editor.ql-blank:before{color:#0009;content:attr(data-placeholder);font-style:italic;left:15px;pointer-events:none;position:absolute;right:15px}.ql-snow.ql-toolbar:after,.ql-snow .ql-toolbar:after{clear:both;content:"";display:table}.ql-snow.ql-toolbar button,.ql-snow .ql-toolbar button{background:none;border:none;cursor:pointer;display:inline-block;float:left;height:24px;padding:3px 5px;width:28px}.ql-snow.ql-toolbar button svg,.ql-snow .ql-toolbar button svg{float:left;height:100%}.ql-snow.ql-toolbar button:active:hover,.ql-snow .ql-toolbar button:active:hover{outline:none}.ql-snow.ql-toolbar input.ql-image[type=file],.ql-snow .ql-toolbar input.ql-image[type=file]{display:none}.ql-snow.ql-toolbar button:hover,.ql-snow .ql-toolbar button:hover,.ql-snow.ql-toolbar button:focus,.ql-snow .ql-toolbar button:focus,.ql-snow.ql-toolbar button.ql-active,.ql-snow .ql-toolbar button.ql-active,.ql-snow.ql-toolbar .ql-picker-label:hover,.ql-snow .ql-toolbar .ql-picker-label:hover,.ql-snow.ql-toolbar .ql-picker-label.ql-active,.ql-snow .ql-toolbar .ql-picker-label.ql-active,.ql-snow.ql-toolbar .ql-picker-item:hover,.ql-snow .ql-toolbar .ql-picker-item:hover,.ql-snow.ql-toolbar .ql-picker-item.ql-selected,.ql-snow .ql-toolbar .ql-picker-item.ql-selected{color:#06c}.ql-snow.ql-toolbar button:hover .ql-fill,.ql-snow .ql-toolbar button:hover .ql-fill,.ql-snow.ql-toolbar button:focus .ql-fill,.ql-snow .ql-toolbar button:focus .ql-fill,.ql-snow.ql-toolbar button.ql-active .ql-fill,.ql-snow .ql-toolbar button.ql-active .ql-fill,.ql-snow.ql-toolbar .ql-picker-label:hover .ql-fill,.ql-snow .ql-toolbar .ql-picker-label:hover .ql-fill,.ql-snow.ql-toolbar .ql-picker-label.ql-active .ql-fill,.ql-snow .ql-toolbar .ql-picker-label.ql-active .ql-fill,.ql-snow.ql-toolbar .ql-picker-item:hover .ql-fill,.ql-snow .ql-toolbar .ql-picker-item:hover .ql-fill,.ql-snow.ql-toolbar .ql-picker-item.ql-selected .ql-fill,.ql-snow .ql-toolbar .ql-picker-item.ql-selected .ql-fill,.ql-snow.ql-toolbar button:hover .ql-stroke.ql-fill,.ql-snow .ql-toolbar button:hover .ql-stroke.ql-fill,.ql-snow.ql-toolbar button:focus .ql-stroke.ql-fill,.ql-snow .ql-toolbar button:focus .ql-stroke.ql-fill,.ql-snow.ql-toolbar button.ql-active .ql-stroke.ql-fill,.ql-snow .ql-toolbar button.ql-active .ql-stroke.ql-fill,.ql-snow.ql-toolbar .ql-picker-label:hover .ql-stroke.ql-fill,.ql-snow .ql-toolbar .ql-picker-label:hover .ql-stroke.ql-fill,.ql-snow.ql-toolbar .ql-picker-label.ql-active .ql-stroke.ql-fill,.ql-snow .ql-toolbar .ql-picker-label.ql-active .ql-stroke.ql-fill,.ql-snow.ql-toolbar .ql-picker-item:hover .ql-stroke.ql-fill,.ql-snow .ql-toolbar .ql-picker-item:hover .ql-stroke.ql-fill,.ql-snow.ql-toolbar .ql-picker-item.ql-selected .ql-stroke.ql-fill,.ql-snow .ql-toolbar .ql-picker-item.ql-selected .ql-stroke.ql-fill{fill:#06c}.ql-snow.ql-toolbar button:hover .ql-stroke,.ql-snow .ql-toolbar button:hover .ql-stroke,.ql-snow.ql-toolbar button:focus .ql-stroke,.ql-snow .ql-toolbar button:focus .ql-stroke,.ql-snow.ql-toolbar button.ql-active .ql-stroke,.ql-snow .ql-toolbar button.ql-active .ql-stroke,.ql-snow.ql-toolbar .ql-picker-label:hover .ql-stroke,.ql-snow .ql-toolbar .ql-picker-label:hover .ql-stroke,.ql-snow.ql-toolbar .ql-picker-label.ql-active .ql-stroke,.ql-snow .ql-toolbar .ql-picker-label.ql-active .ql-stroke,.ql-snow.ql-toolbar .ql-picker-item:hover .ql-stroke,.ql-snow .ql-toolbar .ql-picker-item:hover .ql-stroke,.ql-snow.ql-toolbar .ql-picker-item.ql-selected .ql-stroke,.ql-snow .ql-toolbar .ql-picker-item.ql-selected .ql-stroke,.ql-snow.ql-toolbar button:hover .ql-stroke-miter,.ql-snow .ql-toolbar button:hover .ql-stroke-miter,.ql-snow.ql-toolbar button:focus .ql-stroke-miter,.ql-snow .ql-toolbar button:focus .ql-stroke-miter,.ql-snow.ql-toolbar button.ql-active .ql-stroke-miter,.ql-snow .ql-toolbar button.ql-active .ql-stroke-miter,.ql-snow.ql-toolbar .ql-picker-label:hover .ql-stroke-miter,.ql-snow .ql-toolbar .ql-picker-label:hover .ql-stroke-miter,.ql-snow.ql-toolbar .ql-picker-label.ql-active .ql-stroke-miter,.ql-snow .ql-toolbar .ql-picker-label.ql-active .ql-stroke-miter,.ql-snow.ql-toolbar .ql-picker-item:hover .ql-stroke-miter,.ql-snow .ql-toolbar .ql-picker-item:hover .ql-stroke-miter,.ql-snow.ql-toolbar .ql-picker-item.ql-selected .ql-stroke-miter,.ql-snow .ql-toolbar .ql-picker-item.ql-selected .ql-stroke-miter{stroke:#06c}@media (pointer: coarse){.ql-snow.ql-toolbar button:hover:not(.ql-active),.ql-snow .ql-toolbar button:hover:not(.ql-active){color:#444}.ql-snow.ql-toolbar button:hover:not(.ql-active) .ql-fill,.ql-snow .ql-toolbar button:hover:not(.ql-active) .ql-fill,.ql-snow.ql-toolbar button:hover:not(.ql-active) .ql-stroke.ql-fill,.ql-snow .ql-toolbar button:hover:not(.ql-active) .ql-stroke.ql-fill{fill:#444}.ql-snow.ql-toolbar button:hover:not(.ql-active) .ql-stroke,.ql-snow .ql-toolbar button:hover:not(.ql-active) .ql-stroke,.ql-snow.ql-toolbar button:hover:not(.ql-active) .ql-stroke-miter,.ql-snow .ql-toolbar button:hover:not(.ql-active) .ql-stroke-miter{stroke:#444}}.ql-snow,.ql-snow *{box-sizing:border-box}.ql-snow .ql-hidden{display:none}.ql-snow .ql-out-bottom,.ql-snow .ql-out-top{visibility:hidden}.ql-snow .ql-tooltip{position:absolute;transform:translateY(10px)}.ql-snow .ql-tooltip a{cursor:pointer;text-decoration:none}.ql-snow .ql-tooltip.ql-flip{transform:translateY(-10px)}.ql-snow .ql-formats{display:inline-block;vertical-align:middle}.ql-snow .ql-formats:after{clear:both;content:"";display:table}.ql-snow .ql-stroke{fill:none;stroke:#444;stroke-linecap:round;stroke-linejoin:round;stroke-width:2}.ql-snow .ql-stroke-miter{fill:none;stroke:#444;stroke-miterlimit:10;stroke-width:2}.ql-snow .ql-fill,.ql-snow .ql-stroke.ql-fill{fill:#444}.ql-snow .ql-empty{fill:none}.ql-snow .ql-even{fill-rule:evenodd}.ql-snow .ql-thin,.ql-snow .ql-stroke.ql-thin{stroke-width:1}.ql-snow .ql-transparent{opacity:.4}.ql-snow .ql-direction svg:last-child{display:none}.ql-snow .ql-direction.ql-active svg:last-child{display:inline}.ql-snow .ql-direction.ql-active svg:first-child{display:none}.ql-snow .ql-editor h1{font-size:2em}.ql-snow .ql-editor h2{font-size:1.5em}.ql-snow .ql-editor h3{font-size:1.17em}.ql-snow .ql-editor h4{font-size:1em}.ql-snow .ql-editor h5{font-size:.83em}.ql-snow .ql-editor h6{font-size:.67em}.ql-snow .ql-editor a{text-decoration:underline}.ql-snow .ql-editor blockquote{border-left:4px solid #ccc;margin-bottom:5px;margin-top:5px;padding-left:16px}.ql-snow .ql-editor code,.ql-snow .ql-editor pre{background-color:#f0f0f0;border-radius:3px}.ql-snow .ql-editor pre{white-space:pre-wrap;margin-bottom:5px;margin-top:5px;padding:5px 10px}.ql-snow .ql-editor code{font-size:85%;padding:2px 4px}.ql-snow .ql-editor pre.ql-syntax{background-color:#23241f;color:#f8f8f2;overflow:visible}.ql-snow .ql-editor img{max-width:100%}.ql-snow .ql-picker{color:#444;display:inline-block;float:left;font-size:14px;font-weight:500;height:24px;position:relative;vertical-align:middle}.ql-snow .ql-picker-label{cursor:pointer;display:inline-block;height:100%;padding-left:8px;padding-right:2px;position:relative;width:100%}.ql-snow .ql-picker-label:before{display:inline-block;line-height:22px}.ql-snow .ql-picker-options{background-color:#fff;display:none;min-width:100%;padding:4px 8px;position:absolute;white-space:nowrap}.ql-snow .ql-picker-options .ql-picker-item{cursor:pointer;display:block;padding-bottom:5px;padding-top:5px}.ql-snow .ql-picker.ql-expanded .ql-picker-label{color:#ccc;z-index:2}.ql-snow .ql-picker.ql-expanded .ql-picker-label .ql-fill{fill:#ccc}.ql-snow .ql-picker.ql-expanded .ql-picker-label .ql-stroke{stroke:#ccc}.ql-snow .ql-picker.ql-expanded .ql-picker-options{display:block;margin-top:-1px;top:100%;z-index:1}.ql-snow .ql-color-picker,.ql-snow .ql-icon-picker{width:28px}.ql-snow .ql-color-picker .ql-picker-label,.ql-snow .ql-icon-picker .ql-picker-label{padding:2px 4px}.ql-snow .ql-color-picker .ql-picker-label svg,.ql-snow .ql-icon-picker .ql-picker-label svg{right:4px}.ql-snow .ql-icon-picker .ql-picker-options{padding:4px 0}.ql-snow .ql-icon-picker .ql-picker-item{height:24px;width:24px;padding:2px 4px}.ql-snow .ql-color-picker .ql-picker-options{padding:3px 5px;width:152px}.ql-snow .ql-color-picker .ql-picker-item{border:1px solid transparent;float:left;height:16px;margin:2px;padding:0;width:16px}.ql-snow .ql-picker:not(.ql-color-picker):not(.ql-icon-picker) svg{position:absolute;margin-top:-9px;right:0;top:50%;width:18px}.ql-snow .ql-picker.ql-header .ql-picker-label[data-label]:not([data-label=""]):before,.ql-snow .ql-picker.ql-font .ql-picker-label[data-label]:not([data-label=""]):before,.ql-snow .ql-picker.ql-size .ql-picker-label[data-label]:not([data-label=""]):before,.ql-snow .ql-picker.ql-header .ql-picker-item[data-label]:not([data-label=""]):before,.ql-snow .ql-picker.ql-font .ql-picker-item[data-label]:not([data-label=""]):before,.ql-snow .ql-picker.ql-size .ql-picker-item[data-label]:not([data-label=""]):before{content:attr(data-label)}.ql-snow .ql-picker.ql-header{width:98px}.ql-snow .ql-picker.ql-header .ql-picker-label:before,.ql-snow .ql-picker.ql-header .ql-picker-item:before{content:"Normal"}.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="1"]:before,.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="1"]:before{content:"Heading 1"}.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="2"]:before,.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="2"]:before{content:"Heading 2"}.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="3"]:before,.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="3"]:before{content:"Heading 3"}.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="4"]:before,.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="4"]:before{content:"Heading 4"}.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="5"]:before,.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="5"]:before{content:"Heading 5"}.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="6"]:before,.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="6"]:before{content:"Heading 6"}.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="1"]:before{font-size:2em}.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="2"]:before{font-size:1.5em}.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="3"]:before{font-size:1.17em}.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="4"]:before{font-size:1em}.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="5"]:before{font-size:.83em}.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="6"]:before{font-size:.67em}.ql-snow .ql-picker.ql-font{width:108px}.ql-snow .ql-picker.ql-font .ql-picker-label:before,.ql-snow .ql-picker.ql-font .ql-picker-item:before{content:"Sans Serif"}.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=serif]:before,.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=serif]:before{content:"Serif"}.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=monospace]:before,.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=monospace]:before{content:"Monospace"}.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=serif]:before{font-family:Georgia,Times New Roman,serif}.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=monospace]:before{font-family:Monaco,Courier New,monospace}.ql-snow .ql-picker.ql-size{width:98px}.ql-snow .ql-picker.ql-size .ql-picker-label:before,.ql-snow .ql-picker.ql-size .ql-picker-item:before{content:"Normal"}.ql-snow .ql-picker.ql-size .ql-picker-label[data-value=small]:before,.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=small]:before{content:"Small"}.ql-snow .ql-picker.ql-size .ql-picker-label[data-value=large]:before,.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=large]:before{content:"Large"}.ql-snow .ql-picker.ql-size .ql-picker-label[data-value=huge]:before,.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=huge]:before{content:"Huge"}.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=small]:before{font-size:10px}.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=large]:before{font-size:18px}.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=huge]:before{font-size:32px}.ql-snow .ql-color-picker.ql-background .ql-picker-item{background-color:#fff}.ql-snow .ql-color-picker.ql-color .ql-picker-item{background-color:#000}.ql-toolbar.ql-snow{border:1px solid #ccc;box-sizing:border-box;font-family:Helvetica Neue,Helvetica,Arial,sans-serif;padding:8px}.ql-toolbar.ql-snow .ql-formats{margin-right:15px}.ql-toolbar.ql-snow .ql-picker-label{border:1px solid transparent}.ql-toolbar.ql-snow .ql-picker-options{border:1px solid transparent;box-shadow:#0003 0 2px 8px}.ql-toolbar.ql-snow .ql-picker.ql-expanded .ql-picker-label,.ql-toolbar.ql-snow .ql-picker.ql-expanded .ql-picker-options{border-color:#ccc}.ql-toolbar.ql-snow .ql-color-picker .ql-picker-item.ql-selected,.ql-toolbar.ql-snow .ql-color-picker .ql-picker-item:hover{border-color:#000}.ql-toolbar.ql-snow+.ql-container.ql-snow{border-top:0px}.ql-snow .ql-tooltip{background-color:#fff;border:1px solid #ccc;box-shadow:0 0 5px #ddd;color:#444;padding:5px 12px;white-space:nowrap}.ql-snow .ql-tooltip:before{content:"Visit URL:";line-height:26px;margin-right:8px}.ql-snow .ql-tooltip input[type=text]{display:none;border:1px solid #ccc;font-size:13px;height:26px;margin:0;padding:3px 5px;width:170px}.ql-snow .ql-tooltip a.ql-preview{display:inline-block;max-width:200px;overflow-x:hidden;text-overflow:ellipsis;vertical-align:top}.ql-snow .ql-tooltip a.ql-action:after{border-right:1px solid #ccc;content:"Edit";margin-left:16px;padding-right:8px}.ql-snow .ql-tooltip a.ql-remove:before{content:"Remove";margin-left:8px}.ql-snow .ql-tooltip a{line-height:26px}.ql-snow .ql-tooltip.ql-editing a.ql-preview,.ql-snow .ql-tooltip.ql-editing a.ql-remove{display:none}.ql-snow .ql-tooltip.ql-editing input[type=text]{display:inline-block}.ql-snow .ql-tooltip.ql-editing a.ql-action:after{border-right:0px;content:"Save";padding-right:0}.ql-snow .ql-tooltip[data-mode=link]:before{content:"Enter link:"}.ql-snow .ql-tooltip[data-mode=formula]:before{content:"Enter formula:"}.ql-snow .ql-tooltip[data-mode=video]:before{content:"Enter video:"}.ql-snow a{color:#06c}.ql-container.ql-snow{border:1px solid #ccc}/*! + * Quill Editor v1.3.7 + * https://quilljs.com/ + * Copyright (c) 2014, Jason Chen + * Copyright (c) 2013, salesforce.com + */.ql-container{box-sizing:border-box;font-family:Helvetica,Arial,sans-serif;font-size:13px;height:100%;margin:0;position:relative}.ql-container.ql-disabled .ql-tooltip{visibility:hidden}.ql-container.ql-disabled .ql-editor ul[data-checked]>li:before{pointer-events:none}.ql-clipboard{left:-100000px;height:1px;overflow-y:hidden;position:absolute;top:50%}.ql-clipboard p{margin:0;padding:0}.ql-editor{box-sizing:border-box;line-height:1.42;height:100%;outline:none;overflow-y:auto;padding:12px 15px;tab-size:4;-moz-tab-size:4;text-align:left;white-space:pre-wrap;word-wrap:break-word}.ql-editor>*{cursor:text}.ql-editor p,.ql-editor ol,.ql-editor ul,.ql-editor pre,.ql-editor blockquote,.ql-editor h1,.ql-editor h2,.ql-editor h3,.ql-editor h4,.ql-editor h5,.ql-editor h6{margin:0;padding:0;counter-reset:list-1 list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9}.ql-editor ol,.ql-editor ul{padding-left:1.5em}.ql-editor ol>li,.ql-editor ul>li{list-style-type:none}.ql-editor ul>li:before{content:"\2022"}.ql-editor ul[data-checked=true],.ql-editor ul[data-checked=false]{pointer-events:none}.ql-editor ul[data-checked=true]>li *,.ql-editor ul[data-checked=false]>li *{pointer-events:all}.ql-editor ul[data-checked=true]>li:before,.ql-editor ul[data-checked=false]>li:before{color:#777;cursor:pointer;pointer-events:all}.ql-editor ul[data-checked=true]>li:before{content:"\2611"}.ql-editor ul[data-checked=false]>li:before{content:"\2610"}.ql-editor li:before{display:inline-block;white-space:nowrap;width:1.2em}.ql-editor li:not(.ql-direction-rtl):before{margin-left:-1.5em;margin-right:.3em;text-align:right}.ql-editor li.ql-direction-rtl:before{margin-left:.3em;margin-right:-1.5em}.ql-editor ol li:not(.ql-direction-rtl),.ql-editor ul li:not(.ql-direction-rtl){padding-left:1.5em}.ql-editor ol li.ql-direction-rtl,.ql-editor ul li.ql-direction-rtl{padding-right:1.5em}.ql-editor ol li{counter-reset:list-1 list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9;counter-increment:list-0}.ql-editor ol li:before{content:counter(list-0,decimal) ". "}.ql-editor ol li.ql-indent-1{counter-increment:list-1}.ql-editor ol li.ql-indent-1:before{content:counter(list-1,lower-alpha) ". "}.ql-editor ol li.ql-indent-1{counter-reset:list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9}.ql-editor ol li.ql-indent-2{counter-increment:list-2}.ql-editor ol li.ql-indent-2:before{content:counter(list-2,lower-roman) ". "}.ql-editor ol li.ql-indent-2{counter-reset:list-3 list-4 list-5 list-6 list-7 list-8 list-9}.ql-editor ol li.ql-indent-3{counter-increment:list-3}.ql-editor ol li.ql-indent-3:before{content:counter(list-3,decimal) ". "}.ql-editor ol li.ql-indent-3{counter-reset:list-4 list-5 list-6 list-7 list-8 list-9}.ql-editor ol li.ql-indent-4{counter-increment:list-4}.ql-editor ol li.ql-indent-4:before{content:counter(list-4,lower-alpha) ". "}.ql-editor ol li.ql-indent-4{counter-reset:list-5 list-6 list-7 list-8 list-9}.ql-editor ol li.ql-indent-5{counter-increment:list-5}.ql-editor ol li.ql-indent-5:before{content:counter(list-5,lower-roman) ". "}.ql-editor ol li.ql-indent-5{counter-reset:list-6 list-7 list-8 list-9}.ql-editor ol li.ql-indent-6{counter-increment:list-6}.ql-editor ol li.ql-indent-6:before{content:counter(list-6,decimal) ". "}.ql-editor ol li.ql-indent-6{counter-reset:list-7 list-8 list-9}.ql-editor ol li.ql-indent-7{counter-increment:list-7}.ql-editor ol li.ql-indent-7:before{content:counter(list-7,lower-alpha) ". "}.ql-editor ol li.ql-indent-7{counter-reset:list-8 list-9}.ql-editor ol li.ql-indent-8{counter-increment:list-8}.ql-editor ol li.ql-indent-8:before{content:counter(list-8,lower-roman) ". "}.ql-editor ol li.ql-indent-8{counter-reset:list-9}.ql-editor ol li.ql-indent-9{counter-increment:list-9}.ql-editor ol li.ql-indent-9:before{content:counter(list-9,decimal) ". "}.ql-editor .ql-indent-1:not(.ql-direction-rtl){padding-left:3em}.ql-editor li.ql-indent-1:not(.ql-direction-rtl){padding-left:4.5em}.ql-editor .ql-indent-1.ql-direction-rtl.ql-align-right{padding-right:3em}.ql-editor li.ql-indent-1.ql-direction-rtl.ql-align-right{padding-right:4.5em}.ql-editor .ql-indent-2:not(.ql-direction-rtl){padding-left:6em}.ql-editor li.ql-indent-2:not(.ql-direction-rtl){padding-left:7.5em}.ql-editor .ql-indent-2.ql-direction-rtl.ql-align-right{padding-right:6em}.ql-editor li.ql-indent-2.ql-direction-rtl.ql-align-right{padding-right:7.5em}.ql-editor .ql-indent-3:not(.ql-direction-rtl){padding-left:9em}.ql-editor li.ql-indent-3:not(.ql-direction-rtl){padding-left:10.5em}.ql-editor .ql-indent-3.ql-direction-rtl.ql-align-right{padding-right:9em}.ql-editor li.ql-indent-3.ql-direction-rtl.ql-align-right{padding-right:10.5em}.ql-editor .ql-indent-4:not(.ql-direction-rtl){padding-left:12em}.ql-editor li.ql-indent-4:not(.ql-direction-rtl){padding-left:13.5em}.ql-editor .ql-indent-4.ql-direction-rtl.ql-align-right{padding-right:12em}.ql-editor li.ql-indent-4.ql-direction-rtl.ql-align-right{padding-right:13.5em}.ql-editor .ql-indent-5:not(.ql-direction-rtl){padding-left:15em}.ql-editor li.ql-indent-5:not(.ql-direction-rtl){padding-left:16.5em}.ql-editor .ql-indent-5.ql-direction-rtl.ql-align-right{padding-right:15em}.ql-editor li.ql-indent-5.ql-direction-rtl.ql-align-right{padding-right:16.5em}.ql-editor .ql-indent-6:not(.ql-direction-rtl){padding-left:18em}.ql-editor li.ql-indent-6:not(.ql-direction-rtl){padding-left:19.5em}.ql-editor .ql-indent-6.ql-direction-rtl.ql-align-right{padding-right:18em}.ql-editor li.ql-indent-6.ql-direction-rtl.ql-align-right{padding-right:19.5em}.ql-editor .ql-indent-7:not(.ql-direction-rtl){padding-left:21em}.ql-editor li.ql-indent-7:not(.ql-direction-rtl){padding-left:22.5em}.ql-editor .ql-indent-7.ql-direction-rtl.ql-align-right{padding-right:21em}.ql-editor li.ql-indent-7.ql-direction-rtl.ql-align-right{padding-right:22.5em}.ql-editor .ql-indent-8:not(.ql-direction-rtl){padding-left:24em}.ql-editor li.ql-indent-8:not(.ql-direction-rtl){padding-left:25.5em}.ql-editor .ql-indent-8.ql-direction-rtl.ql-align-right{padding-right:24em}.ql-editor li.ql-indent-8.ql-direction-rtl.ql-align-right{padding-right:25.5em}.ql-editor .ql-indent-9:not(.ql-direction-rtl){padding-left:27em}.ql-editor li.ql-indent-9:not(.ql-direction-rtl){padding-left:28.5em}.ql-editor .ql-indent-9.ql-direction-rtl.ql-align-right{padding-right:27em}.ql-editor li.ql-indent-9.ql-direction-rtl.ql-align-right{padding-right:28.5em}.ql-editor .ql-video{display:block;max-width:100%}.ql-editor .ql-video.ql-align-center{margin:0 auto}.ql-editor .ql-video.ql-align-right{margin:0 0 0 auto}.ql-editor .ql-bg-black{background-color:#000}.ql-editor .ql-bg-red{background-color:#e60000}.ql-editor .ql-bg-orange{background-color:#f90}.ql-editor .ql-bg-yellow{background-color:#ff0}.ql-editor .ql-bg-green{background-color:#008a00}.ql-editor .ql-bg-blue{background-color:#06c}.ql-editor .ql-bg-purple{background-color:#93f}.ql-editor .ql-color-white{color:#fff}.ql-editor .ql-color-red{color:#e60000}.ql-editor .ql-color-orange{color:#f90}.ql-editor .ql-color-yellow{color:#ff0}.ql-editor .ql-color-green{color:#008a00}.ql-editor .ql-color-blue{color:#06c}.ql-editor .ql-color-purple{color:#93f}.ql-editor .ql-font-serif{font-family:Georgia,Times New Roman,serif}.ql-editor .ql-font-monospace{font-family:Monaco,Courier New,monospace}.ql-editor .ql-size-small{font-size:.75em}.ql-editor .ql-size-large{font-size:1.5em}.ql-editor .ql-size-huge{font-size:2.5em}.ql-editor .ql-direction-rtl{direction:rtl;text-align:inherit}.ql-editor .ql-align-center{text-align:center}.ql-editor .ql-align-justify{text-align:justify}.ql-editor .ql-align-right{text-align:right}.ql-editor.ql-blank:before{color:#0009;content:attr(data-placeholder);font-style:italic;left:15px;pointer-events:none;position:absolute;right:15px}.ql-bubble.ql-toolbar:after,.ql-bubble .ql-toolbar:after{clear:both;content:"";display:table}.ql-bubble.ql-toolbar button,.ql-bubble .ql-toolbar button{background:none;border:none;cursor:pointer;display:inline-block;float:left;height:24px;padding:3px 5px;width:28px}.ql-bubble.ql-toolbar button svg,.ql-bubble .ql-toolbar button svg{float:left;height:100%}.ql-bubble.ql-toolbar button:active:hover,.ql-bubble .ql-toolbar button:active:hover{outline:none}.ql-bubble.ql-toolbar input.ql-image[type=file],.ql-bubble .ql-toolbar input.ql-image[type=file]{display:none}.ql-bubble.ql-toolbar button:hover,.ql-bubble .ql-toolbar button:hover,.ql-bubble.ql-toolbar button:focus,.ql-bubble .ql-toolbar button:focus,.ql-bubble.ql-toolbar button.ql-active,.ql-bubble .ql-toolbar button.ql-active,.ql-bubble.ql-toolbar .ql-picker-label:hover,.ql-bubble .ql-toolbar .ql-picker-label:hover,.ql-bubble.ql-toolbar .ql-picker-label.ql-active,.ql-bubble .ql-toolbar .ql-picker-label.ql-active,.ql-bubble.ql-toolbar .ql-picker-item:hover,.ql-bubble .ql-toolbar .ql-picker-item:hover,.ql-bubble.ql-toolbar .ql-picker-item.ql-selected,.ql-bubble .ql-toolbar .ql-picker-item.ql-selected{color:#fff}.ql-bubble.ql-toolbar button:hover .ql-fill,.ql-bubble .ql-toolbar button:hover .ql-fill,.ql-bubble.ql-toolbar button:focus .ql-fill,.ql-bubble .ql-toolbar button:focus .ql-fill,.ql-bubble.ql-toolbar button.ql-active .ql-fill,.ql-bubble .ql-toolbar button.ql-active .ql-fill,.ql-bubble.ql-toolbar .ql-picker-label:hover .ql-fill,.ql-bubble .ql-toolbar .ql-picker-label:hover .ql-fill,.ql-bubble.ql-toolbar .ql-picker-label.ql-active .ql-fill,.ql-bubble .ql-toolbar .ql-picker-label.ql-active .ql-fill,.ql-bubble.ql-toolbar .ql-picker-item:hover .ql-fill,.ql-bubble .ql-toolbar .ql-picker-item:hover .ql-fill,.ql-bubble.ql-toolbar .ql-picker-item.ql-selected .ql-fill,.ql-bubble .ql-toolbar .ql-picker-item.ql-selected .ql-fill,.ql-bubble.ql-toolbar button:hover .ql-stroke.ql-fill,.ql-bubble .ql-toolbar button:hover .ql-stroke.ql-fill,.ql-bubble.ql-toolbar button:focus .ql-stroke.ql-fill,.ql-bubble .ql-toolbar button:focus .ql-stroke.ql-fill,.ql-bubble.ql-toolbar button.ql-active .ql-stroke.ql-fill,.ql-bubble .ql-toolbar button.ql-active .ql-stroke.ql-fill,.ql-bubble.ql-toolbar .ql-picker-label:hover .ql-stroke.ql-fill,.ql-bubble .ql-toolbar .ql-picker-label:hover .ql-stroke.ql-fill,.ql-bubble.ql-toolbar .ql-picker-label.ql-active .ql-stroke.ql-fill,.ql-bubble .ql-toolbar .ql-picker-label.ql-active .ql-stroke.ql-fill,.ql-bubble.ql-toolbar .ql-picker-item:hover .ql-stroke.ql-fill,.ql-bubble .ql-toolbar .ql-picker-item:hover .ql-stroke.ql-fill,.ql-bubble.ql-toolbar .ql-picker-item.ql-selected .ql-stroke.ql-fill,.ql-bubble .ql-toolbar .ql-picker-item.ql-selected .ql-stroke.ql-fill{fill:#fff}.ql-bubble.ql-toolbar button:hover .ql-stroke,.ql-bubble .ql-toolbar button:hover .ql-stroke,.ql-bubble.ql-toolbar button:focus .ql-stroke,.ql-bubble .ql-toolbar button:focus .ql-stroke,.ql-bubble.ql-toolbar button.ql-active .ql-stroke,.ql-bubble .ql-toolbar button.ql-active .ql-stroke,.ql-bubble.ql-toolbar .ql-picker-label:hover .ql-stroke,.ql-bubble .ql-toolbar .ql-picker-label:hover .ql-stroke,.ql-bubble.ql-toolbar .ql-picker-label.ql-active .ql-stroke,.ql-bubble .ql-toolbar .ql-picker-label.ql-active .ql-stroke,.ql-bubble.ql-toolbar .ql-picker-item:hover .ql-stroke,.ql-bubble .ql-toolbar .ql-picker-item:hover .ql-stroke,.ql-bubble.ql-toolbar .ql-picker-item.ql-selected .ql-stroke,.ql-bubble .ql-toolbar .ql-picker-item.ql-selected .ql-stroke,.ql-bubble.ql-toolbar button:hover .ql-stroke-miter,.ql-bubble .ql-toolbar button:hover .ql-stroke-miter,.ql-bubble.ql-toolbar button:focus .ql-stroke-miter,.ql-bubble .ql-toolbar button:focus .ql-stroke-miter,.ql-bubble.ql-toolbar button.ql-active .ql-stroke-miter,.ql-bubble .ql-toolbar button.ql-active .ql-stroke-miter,.ql-bubble.ql-toolbar .ql-picker-label:hover .ql-stroke-miter,.ql-bubble .ql-toolbar .ql-picker-label:hover .ql-stroke-miter,.ql-bubble.ql-toolbar .ql-picker-label.ql-active .ql-stroke-miter,.ql-bubble .ql-toolbar .ql-picker-label.ql-active .ql-stroke-miter,.ql-bubble.ql-toolbar .ql-picker-item:hover .ql-stroke-miter,.ql-bubble .ql-toolbar .ql-picker-item:hover .ql-stroke-miter,.ql-bubble.ql-toolbar .ql-picker-item.ql-selected .ql-stroke-miter,.ql-bubble .ql-toolbar .ql-picker-item.ql-selected .ql-stroke-miter{stroke:#fff}@media (pointer: coarse){.ql-bubble.ql-toolbar button:hover:not(.ql-active),.ql-bubble .ql-toolbar button:hover:not(.ql-active){color:#ccc}.ql-bubble.ql-toolbar button:hover:not(.ql-active) .ql-fill,.ql-bubble .ql-toolbar button:hover:not(.ql-active) .ql-fill,.ql-bubble.ql-toolbar button:hover:not(.ql-active) .ql-stroke.ql-fill,.ql-bubble .ql-toolbar button:hover:not(.ql-active) .ql-stroke.ql-fill{fill:#ccc}.ql-bubble.ql-toolbar button:hover:not(.ql-active) .ql-stroke,.ql-bubble .ql-toolbar button:hover:not(.ql-active) .ql-stroke,.ql-bubble.ql-toolbar button:hover:not(.ql-active) .ql-stroke-miter,.ql-bubble .ql-toolbar button:hover:not(.ql-active) .ql-stroke-miter{stroke:#ccc}}.ql-bubble,.ql-bubble *{box-sizing:border-box}.ql-bubble .ql-hidden{display:none}.ql-bubble .ql-out-bottom,.ql-bubble .ql-out-top{visibility:hidden}.ql-bubble .ql-tooltip{position:absolute;transform:translateY(10px)}.ql-bubble .ql-tooltip a{cursor:pointer;text-decoration:none}.ql-bubble .ql-tooltip.ql-flip{transform:translateY(-10px)}.ql-bubble .ql-formats{display:inline-block;vertical-align:middle}.ql-bubble .ql-formats:after{clear:both;content:"";display:table}.ql-bubble .ql-stroke{fill:none;stroke:#ccc;stroke-linecap:round;stroke-linejoin:round;stroke-width:2}.ql-bubble .ql-stroke-miter{fill:none;stroke:#ccc;stroke-miterlimit:10;stroke-width:2}.ql-bubble .ql-fill,.ql-bubble .ql-stroke.ql-fill{fill:#ccc}.ql-bubble .ql-empty{fill:none}.ql-bubble .ql-even{fill-rule:evenodd}.ql-bubble .ql-thin,.ql-bubble .ql-stroke.ql-thin{stroke-width:1}.ql-bubble .ql-transparent{opacity:.4}.ql-bubble .ql-direction svg:last-child{display:none}.ql-bubble .ql-direction.ql-active svg:last-child{display:inline}.ql-bubble .ql-direction.ql-active svg:first-child{display:none}.ql-bubble .ql-editor h1{font-size:2em}.ql-bubble .ql-editor h2{font-size:1.5em}.ql-bubble .ql-editor h3{font-size:1.17em}.ql-bubble .ql-editor h4{font-size:1em}.ql-bubble .ql-editor h5{font-size:.83em}.ql-bubble .ql-editor h6{font-size:.67em}.ql-bubble .ql-editor a{text-decoration:underline}.ql-bubble .ql-editor blockquote{border-left:4px solid #ccc;margin-bottom:5px;margin-top:5px;padding-left:16px}.ql-bubble .ql-editor code,.ql-bubble .ql-editor pre{background-color:#f0f0f0;border-radius:3px}.ql-bubble .ql-editor pre{white-space:pre-wrap;margin-bottom:5px;margin-top:5px;padding:5px 10px}.ql-bubble .ql-editor code{font-size:85%;padding:2px 4px}.ql-bubble .ql-editor pre.ql-syntax{background-color:#23241f;color:#f8f8f2;overflow:visible}.ql-bubble .ql-editor img{max-width:100%}.ql-bubble .ql-picker{color:#ccc;display:inline-block;float:left;font-size:14px;font-weight:500;height:24px;position:relative;vertical-align:middle}.ql-bubble .ql-picker-label{cursor:pointer;display:inline-block;height:100%;padding-left:8px;padding-right:2px;position:relative;width:100%}.ql-bubble .ql-picker-label:before{display:inline-block;line-height:22px}.ql-bubble .ql-picker-options{background-color:#444;display:none;min-width:100%;padding:4px 8px;position:absolute;white-space:nowrap}.ql-bubble .ql-picker-options .ql-picker-item{cursor:pointer;display:block;padding-bottom:5px;padding-top:5px}.ql-bubble .ql-picker.ql-expanded .ql-picker-label{color:#777;z-index:2}.ql-bubble .ql-picker.ql-expanded .ql-picker-label .ql-fill{fill:#777}.ql-bubble .ql-picker.ql-expanded .ql-picker-label .ql-stroke{stroke:#777}.ql-bubble .ql-picker.ql-expanded .ql-picker-options{display:block;margin-top:-1px;top:100%;z-index:1}.ql-bubble .ql-color-picker,.ql-bubble .ql-icon-picker{width:28px}.ql-bubble .ql-color-picker .ql-picker-label,.ql-bubble .ql-icon-picker .ql-picker-label{padding:2px 4px}.ql-bubble .ql-color-picker .ql-picker-label svg,.ql-bubble .ql-icon-picker .ql-picker-label svg{right:4px}.ql-bubble .ql-icon-picker .ql-picker-options{padding:4px 0}.ql-bubble .ql-icon-picker .ql-picker-item{height:24px;width:24px;padding:2px 4px}.ql-bubble .ql-color-picker .ql-picker-options{padding:3px 5px;width:152px}.ql-bubble .ql-color-picker .ql-picker-item{border:1px solid transparent;float:left;height:16px;margin:2px;padding:0;width:16px}.ql-bubble .ql-picker:not(.ql-color-picker):not(.ql-icon-picker) svg{position:absolute;margin-top:-9px;right:0;top:50%;width:18px}.ql-bubble .ql-picker.ql-header .ql-picker-label[data-label]:not([data-label=""]):before,.ql-bubble .ql-picker.ql-font .ql-picker-label[data-label]:not([data-label=""]):before,.ql-bubble .ql-picker.ql-size .ql-picker-label[data-label]:not([data-label=""]):before,.ql-bubble .ql-picker.ql-header .ql-picker-item[data-label]:not([data-label=""]):before,.ql-bubble .ql-picker.ql-font .ql-picker-item[data-label]:not([data-label=""]):before,.ql-bubble .ql-picker.ql-size .ql-picker-item[data-label]:not([data-label=""]):before{content:attr(data-label)}.ql-bubble .ql-picker.ql-header{width:98px}.ql-bubble .ql-picker.ql-header .ql-picker-label:before,.ql-bubble .ql-picker.ql-header .ql-picker-item:before{content:"Normal"}.ql-bubble .ql-picker.ql-header .ql-picker-label[data-value="1"]:before,.ql-bubble .ql-picker.ql-header .ql-picker-item[data-value="1"]:before{content:"Heading 1"}.ql-bubble .ql-picker.ql-header .ql-picker-label[data-value="2"]:before,.ql-bubble .ql-picker.ql-header .ql-picker-item[data-value="2"]:before{content:"Heading 2"}.ql-bubble .ql-picker.ql-header .ql-picker-label[data-value="3"]:before,.ql-bubble .ql-picker.ql-header .ql-picker-item[data-value="3"]:before{content:"Heading 3"}.ql-bubble .ql-picker.ql-header .ql-picker-label[data-value="4"]:before,.ql-bubble .ql-picker.ql-header .ql-picker-item[data-value="4"]:before{content:"Heading 4"}.ql-bubble .ql-picker.ql-header .ql-picker-label[data-value="5"]:before,.ql-bubble .ql-picker.ql-header .ql-picker-item[data-value="5"]:before{content:"Heading 5"}.ql-bubble .ql-picker.ql-header .ql-picker-label[data-value="6"]:before,.ql-bubble .ql-picker.ql-header .ql-picker-item[data-value="6"]:before{content:"Heading 6"}.ql-bubble .ql-picker.ql-header .ql-picker-item[data-value="1"]:before{font-size:2em}.ql-bubble .ql-picker.ql-header .ql-picker-item[data-value="2"]:before{font-size:1.5em}.ql-bubble .ql-picker.ql-header .ql-picker-item[data-value="3"]:before{font-size:1.17em}.ql-bubble .ql-picker.ql-header .ql-picker-item[data-value="4"]:before{font-size:1em}.ql-bubble .ql-picker.ql-header .ql-picker-item[data-value="5"]:before{font-size:.83em}.ql-bubble .ql-picker.ql-header .ql-picker-item[data-value="6"]:before{font-size:.67em}.ql-bubble .ql-picker.ql-font{width:108px}.ql-bubble .ql-picker.ql-font .ql-picker-label:before,.ql-bubble .ql-picker.ql-font .ql-picker-item:before{content:"Sans Serif"}.ql-bubble .ql-picker.ql-font .ql-picker-label[data-value=serif]:before,.ql-bubble .ql-picker.ql-font .ql-picker-item[data-value=serif]:before{content:"Serif"}.ql-bubble .ql-picker.ql-font .ql-picker-label[data-value=monospace]:before,.ql-bubble .ql-picker.ql-font .ql-picker-item[data-value=monospace]:before{content:"Monospace"}.ql-bubble .ql-picker.ql-font .ql-picker-item[data-value=serif]:before{font-family:Georgia,Times New Roman,serif}.ql-bubble .ql-picker.ql-font .ql-picker-item[data-value=monospace]:before{font-family:Monaco,Courier New,monospace}.ql-bubble .ql-picker.ql-size{width:98px}.ql-bubble .ql-picker.ql-size .ql-picker-label:before,.ql-bubble .ql-picker.ql-size .ql-picker-item:before{content:"Normal"}.ql-bubble .ql-picker.ql-size .ql-picker-label[data-value=small]:before,.ql-bubble .ql-picker.ql-size .ql-picker-item[data-value=small]:before{content:"Small"}.ql-bubble .ql-picker.ql-size .ql-picker-label[data-value=large]:before,.ql-bubble .ql-picker.ql-size .ql-picker-item[data-value=large]:before{content:"Large"}.ql-bubble .ql-picker.ql-size .ql-picker-label[data-value=huge]:before,.ql-bubble .ql-picker.ql-size .ql-picker-item[data-value=huge]:before{content:"Huge"}.ql-bubble .ql-picker.ql-size .ql-picker-item[data-value=small]:before{font-size:10px}.ql-bubble .ql-picker.ql-size .ql-picker-item[data-value=large]:before{font-size:18px}.ql-bubble .ql-picker.ql-size .ql-picker-item[data-value=huge]:before{font-size:32px}.ql-bubble .ql-color-picker.ql-background .ql-picker-item{background-color:#fff}.ql-bubble .ql-color-picker.ql-color .ql-picker-item{background-color:#000}.ql-bubble .ql-toolbar .ql-formats{margin:8px 12px 8px 0}.ql-bubble .ql-toolbar .ql-formats:first-child{margin-left:12px}.ql-bubble .ql-color-picker svg{margin:1px}.ql-bubble .ql-color-picker .ql-picker-item.ql-selected,.ql-bubble .ql-color-picker .ql-picker-item:hover{border-color:#fff}.ql-bubble .ql-tooltip{background-color:#444;border-radius:25px;color:#fff}.ql-bubble .ql-tooltip-arrow{border-left:6px solid transparent;border-right:6px solid transparent;content:" ";display:block;left:50%;margin-left:-6px;position:absolute}.ql-bubble .ql-tooltip:not(.ql-flip) .ql-tooltip-arrow{border-bottom:6px solid #444;top:-6px}.ql-bubble .ql-tooltip.ql-flip .ql-tooltip-arrow{border-top:6px solid #444;bottom:-6px}.ql-bubble .ql-tooltip.ql-editing .ql-tooltip-editor{display:block}.ql-bubble .ql-tooltip.ql-editing .ql-formats{visibility:hidden}.ql-bubble .ql-tooltip-editor{display:none}.ql-bubble .ql-tooltip-editor input[type=text]{background:transparent;border:none;color:#fff;font-size:13px;height:100%;outline:none;padding:10px 20px;position:absolute;width:100%}.ql-bubble .ql-tooltip-editor a{top:10px;position:absolute;right:20px}.ql-bubble .ql-tooltip-editor a:before{color:#ccc;content:"\d7";font-size:16px;font-weight:700}.ql-container.ql-bubble:not(.ql-disabled) a{position:relative;white-space:nowrap}.ql-container.ql-bubble:not(.ql-disabled) a:before{background-color:#444;border-radius:15px;top:-5px;font-size:12px;color:#fff;content:attr(href);font-weight:400;overflow:hidden;padding:5px 15px;text-decoration:none;z-index:1}.ql-container.ql-bubble:not(.ql-disabled) a:after{border-top:6px solid #444;border-left:6px solid transparent;border-right:6px solid transparent;top:0;content:" ";height:0;width:0}.ql-container.ql-bubble:not(.ql-disabled) a:before,.ql-container.ql-bubble:not(.ql-disabled) a:after{left:0;margin-left:50%;position:absolute;transform:translate(-50%,-100%);transition:visibility 0s ease .2s;visibility:hidden}.ql-container.ql-bubble:not(.ql-disabled) a:hover:before,.ql-container.ql-bubble:not(.ql-disabled) a:hover:after{visibility:visible}.primary-color[data-v-a23436fa]{color:#409eff}.background-opacity[data-v-a23436fa]{background:rgba(64,158,255,.6)}.form-widget-list .ghost[data-v-a23436fa]{content:"";font-size:0;height:3px;box-sizing:border-box;background:#409EFF;border:2px solid #409EFF;outline-width:0;padding:0;overflow:hidden}.el-form-item .el-rate[data-v-a23436fa]{margin-top:8px}.el-form-item--medium .el-radio[data-v-a23436fa]{line-height:36px!important}.el-form-item--medium .el-rate[data-v-a23436fa]{margin-top:8px}.el-form-item--small .el-radio[data-v-a23436fa]{line-height:32px!important}.el-form-item--small .el-rate[data-v-a23436fa]{margin-top:6px}.el-form-item--mini .el-radio[data-v-a23436fa]{line-height:28px!important}.el-form-item--mini .el-rate[data-v-a23436fa]{margin-top:4px}.el-card[data-v-a23436fa]{margin-top:3px;margin-bottom:3px}input[type=password][data-v-a23436fa]::-ms-reveal{display:none}.auto-full-width.el-date-editor.el-input[data-v-a23436fa],.auto-full-width.el-date-editor.el-input__inner[data-v-a23436fa]{width:100%!important}[data-v-a23436fa]::-webkit-scrollbar{width:8px;height:8px}[data-v-a23436fa]::-webkit-scrollbar-track{width:8px;background:rgba(16,31,28,.1);-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-a23436fa]::-webkit-scrollbar-thumb{background-color:#101f1c59;background-clip:padding-box;min-height:28px;-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-a23436fa]::-webkit-scrollbar-thumb:hover{background-color:#101f1cd9}*[data-v-a23436fa]{scrollbar-color:#e5e5e5 #f7f7f9;scrollbar-width:thin}.full-width-input[data-v-a23436fa]{width:100%!important}.primary-color[data-v-038816bf]{color:#409eff}.background-opacity[data-v-038816bf]{background:rgba(64,158,255,.6)}.form-widget-list .ghost[data-v-038816bf]{content:"";font-size:0;height:3px;box-sizing:border-box;background:#409EFF;border:2px solid #409EFF;outline-width:0;padding:0;overflow:hidden}.el-form-item .el-rate[data-v-038816bf]{margin-top:8px}.el-form-item--medium .el-radio[data-v-038816bf]{line-height:36px!important}.el-form-item--medium .el-rate[data-v-038816bf]{margin-top:8px}.el-form-item--small .el-radio[data-v-038816bf]{line-height:32px!important}.el-form-item--small .el-rate[data-v-038816bf]{margin-top:6px}.el-form-item--mini .el-radio[data-v-038816bf]{line-height:28px!important}.el-form-item--mini .el-rate[data-v-038816bf]{margin-top:4px}.el-card[data-v-038816bf]{margin-top:3px;margin-bottom:3px}input[type=password][data-v-038816bf]::-ms-reveal{display:none}.auto-full-width.el-date-editor.el-input[data-v-038816bf],.auto-full-width.el-date-editor.el-input__inner[data-v-038816bf]{width:100%!important}[data-v-038816bf]::-webkit-scrollbar{width:8px;height:8px}[data-v-038816bf]::-webkit-scrollbar-track{width:8px;background:rgba(16,31,28,.1);-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-038816bf]::-webkit-scrollbar-thumb{background-color:#101f1c59;background-clip:padding-box;min-height:28px;-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-038816bf]::-webkit-scrollbar-thumb:hover{background-color:#101f1cd9}*[data-v-038816bf]{scrollbar-color:#e5e5e5 #f7f7f9;scrollbar-width:thin}.full-width-input[data-v-038816bf]{width:100%!important}.primary-color[data-v-92a76556]{color:#409eff}.background-opacity[data-v-92a76556]{background:rgba(64,158,255,.6)}.form-widget-list .ghost[data-v-92a76556]{content:"";font-size:0;height:3px;box-sizing:border-box;background:#409EFF;border:2px solid #409EFF;outline-width:0;padding:0;overflow:hidden}.el-form-item .el-rate[data-v-92a76556]{margin-top:8px}.el-form-item--medium .el-radio[data-v-92a76556]{line-height:36px!important}.el-form-item--medium .el-rate[data-v-92a76556]{margin-top:8px}.el-form-item--small .el-radio[data-v-92a76556]{line-height:32px!important}.el-form-item--small .el-rate[data-v-92a76556]{margin-top:6px}.el-form-item--mini .el-radio[data-v-92a76556]{line-height:28px!important}.el-form-item--mini .el-rate[data-v-92a76556]{margin-top:4px}.el-card[data-v-92a76556]{margin-top:3px;margin-bottom:3px}input[type=password][data-v-92a76556]::-ms-reveal{display:none}.auto-full-width.el-date-editor.el-input[data-v-92a76556],.auto-full-width.el-date-editor.el-input__inner[data-v-92a76556]{width:100%!important}[data-v-92a76556]::-webkit-scrollbar{width:8px;height:8px}[data-v-92a76556]::-webkit-scrollbar-track{width:8px;background:rgba(16,31,28,.1);-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-92a76556]::-webkit-scrollbar-thumb{background-color:#101f1c59;background-clip:padding-box;min-height:28px;-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-92a76556]::-webkit-scrollbar-thumb:hover{background-color:#101f1cd9}*[data-v-92a76556]{scrollbar-color:#e5e5e5 #f7f7f9;scrollbar-width:thin}.full-width-input[data-v-92a76556]{width:100%!important}.primary-color[data-v-95f13fca]{color:#409eff}.background-opacity[data-v-95f13fca]{background:rgba(64,158,255,.6)}.form-widget-list .ghost[data-v-95f13fca]{content:"";font-size:0;height:3px;box-sizing:border-box;background:#409EFF;border:2px solid #409EFF;outline-width:0;padding:0;overflow:hidden}.el-form-item .el-rate[data-v-95f13fca]{margin-top:8px}.el-form-item--medium .el-radio[data-v-95f13fca]{line-height:36px!important}.el-form-item--medium .el-rate[data-v-95f13fca]{margin-top:8px}.el-form-item--small .el-radio[data-v-95f13fca]{line-height:32px!important}.el-form-item--small .el-rate[data-v-95f13fca]{margin-top:6px}.el-form-item--mini .el-radio[data-v-95f13fca]{line-height:28px!important}.el-form-item--mini .el-rate[data-v-95f13fca]{margin-top:4px}.el-card[data-v-95f13fca]{margin-top:3px;margin-bottom:3px}input[type=password][data-v-95f13fca]::-ms-reveal{display:none}.auto-full-width.el-date-editor.el-input[data-v-95f13fca],.auto-full-width.el-date-editor.el-input__inner[data-v-95f13fca]{width:100%!important}[data-v-95f13fca]::-webkit-scrollbar{width:8px;height:8px}[data-v-95f13fca]::-webkit-scrollbar-track{width:8px;background:rgba(16,31,28,.1);-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-95f13fca]::-webkit-scrollbar-thumb{background-color:#101f1c59;background-clip:padding-box;min-height:28px;-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-95f13fca]::-webkit-scrollbar-thumb:hover{background-color:#101f1cd9}*[data-v-95f13fca]{scrollbar-color:#e5e5e5 #f7f7f9;scrollbar-width:thin}.slot-wrapper-design[data-v-95f13fca]{width:100%;min-height:26px;background:linear-gradient(45deg,#ccc 25%,#eee 0,#eee 50%,#ccc 0,#ccc 75%,#eee 0);background-size:20px 20px;text-align:center}.slot-wrapper-design .slot-title[data-v-95f13fca]{font-size:13px}.primary-color[data-v-4071ab53]{color:#409eff}.background-opacity[data-v-4071ab53]{background:rgba(64,158,255,.6)}.form-widget-list .ghost[data-v-4071ab53]{content:"";font-size:0;height:3px;box-sizing:border-box;background:#409EFF;border:2px solid #409EFF;outline-width:0;padding:0;overflow:hidden}.el-form-item .el-rate[data-v-4071ab53]{margin-top:8px}.el-form-item--medium .el-radio[data-v-4071ab53]{line-height:36px!important}.el-form-item--medium .el-rate[data-v-4071ab53]{margin-top:8px}.el-form-item--small .el-radio[data-v-4071ab53]{line-height:32px!important}.el-form-item--small .el-rate[data-v-4071ab53]{margin-top:6px}.el-form-item--mini .el-radio[data-v-4071ab53]{line-height:28px!important}.el-form-item--mini .el-rate[data-v-4071ab53]{margin-top:4px}.el-card[data-v-4071ab53]{margin-top:3px;margin-bottom:3px}input[type=password][data-v-4071ab53]::-ms-reveal{display:none}.auto-full-width.el-date-editor.el-input[data-v-4071ab53],.auto-full-width.el-date-editor.el-input__inner[data-v-4071ab53]{width:100%!important}[data-v-4071ab53]::-webkit-scrollbar{width:8px;height:8px}[data-v-4071ab53]::-webkit-scrollbar-track{width:8px;background:rgba(16,31,28,.1);-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-4071ab53]::-webkit-scrollbar-thumb{background-color:#101f1c59;background-clip:padding-box;min-height:28px;-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-4071ab53]::-webkit-scrollbar-thumb:hover{background-color:#101f1cd9}*[data-v-4071ab53]{scrollbar-color:#e5e5e5 #f7f7f9;scrollbar-width:thin}.primary-color[data-v-3529e848]{color:#409eff}.background-opacity[data-v-3529e848]{background:rgba(64,158,255,.6)}.form-widget-list .ghost[data-v-3529e848]{content:"";font-size:0;height:3px;box-sizing:border-box;background:#409EFF;border:2px solid #409EFF;outline-width:0;padding:0;overflow:hidden}.el-form-item .el-rate[data-v-3529e848]{margin-top:8px}.el-form-item--medium .el-radio[data-v-3529e848]{line-height:36px!important}.el-form-item--medium .el-rate[data-v-3529e848]{margin-top:8px}.el-form-item--small .el-radio[data-v-3529e848]{line-height:32px!important}.el-form-item--small .el-rate[data-v-3529e848]{margin-top:6px}.el-form-item--mini .el-radio[data-v-3529e848]{line-height:28px!important}.el-form-item--mini .el-rate[data-v-3529e848]{margin-top:4px}.el-card[data-v-3529e848]{margin-top:3px;margin-bottom:3px}input[type=password][data-v-3529e848]::-ms-reveal{display:none}.auto-full-width.el-date-editor.el-input[data-v-3529e848],.auto-full-width.el-date-editor.el-input__inner[data-v-3529e848]{width:100%!important}[data-v-3529e848]::-webkit-scrollbar{width:8px;height:8px}[data-v-3529e848]::-webkit-scrollbar-track{width:8px;background:rgba(16,31,28,.1);-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-3529e848]::-webkit-scrollbar-thumb{background-color:#101f1c59;background-clip:padding-box;min-height:28px;-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-3529e848]::-webkit-scrollbar-thumb:hover{background-color:#101f1cd9}*[data-v-3529e848]{scrollbar-color:#e5e5e5 #f7f7f9;scrollbar-width:thin}.full-width-input[data-v-3529e848]{width:100%!important}.primary-color[data-v-072d98c8]{color:#409eff}.background-opacity[data-v-072d98c8]{background:rgba(64,158,255,.6)}.form-widget-list .ghost[data-v-072d98c8]{content:"";font-size:0;height:3px;box-sizing:border-box;background:#409EFF;border:2px solid #409EFF;outline-width:0;padding:0;overflow:hidden}.el-form-item .el-rate[data-v-072d98c8]{margin-top:8px}.el-form-item--medium .el-radio[data-v-072d98c8]{line-height:36px!important}.el-form-item--medium .el-rate[data-v-072d98c8]{margin-top:8px}.el-form-item--small .el-radio[data-v-072d98c8]{line-height:32px!important}.el-form-item--small .el-rate[data-v-072d98c8]{margin-top:6px}.el-form-item--mini .el-radio[data-v-072d98c8]{line-height:28px!important}.el-form-item--mini .el-rate[data-v-072d98c8]{margin-top:4px}.el-card[data-v-072d98c8]{margin-top:3px;margin-bottom:3px}input[type=password][data-v-072d98c8]::-ms-reveal{display:none}.auto-full-width.el-date-editor.el-input[data-v-072d98c8],.auto-full-width.el-date-editor.el-input__inner[data-v-072d98c8]{width:100%!important}[data-v-072d98c8]::-webkit-scrollbar{width:8px;height:8px}[data-v-072d98c8]::-webkit-scrollbar-track{width:8px;background:rgba(16,31,28,.1);-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-072d98c8]::-webkit-scrollbar-thumb{background-color:#101f1c59;background-clip:padding-box;min-height:28px;-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-072d98c8]::-webkit-scrollbar-thumb:hover{background-color:#101f1cd9}*[data-v-072d98c8]{scrollbar-color:#e5e5e5 #f7f7f9;scrollbar-width:thin}.primary-color[data-v-60824824]{color:#409eff}.background-opacity[data-v-60824824]{background:rgba(64,158,255,.6)}.form-widget-list .ghost[data-v-60824824]{content:"";font-size:0;height:3px;box-sizing:border-box;background:#409EFF;border:2px solid #409EFF;outline-width:0;padding:0;overflow:hidden}.el-form-item .el-rate[data-v-60824824]{margin-top:8px}.el-form-item--medium .el-radio[data-v-60824824]{line-height:36px!important}.el-form-item--medium .el-rate[data-v-60824824]{margin-top:8px}.el-form-item--small .el-radio[data-v-60824824]{line-height:32px!important}.el-form-item--small .el-rate[data-v-60824824]{margin-top:6px}.el-form-item--mini .el-radio[data-v-60824824]{line-height:28px!important}.el-form-item--mini .el-rate[data-v-60824824]{margin-top:4px}.el-card[data-v-60824824]{margin-top:3px;margin-bottom:3px}input[type=password][data-v-60824824]::-ms-reveal{display:none}.auto-full-width.el-date-editor.el-input[data-v-60824824],.auto-full-width.el-date-editor.el-input__inner[data-v-60824824]{width:100%!important}[data-v-60824824]::-webkit-scrollbar{width:8px;height:8px}[data-v-60824824]::-webkit-scrollbar-track{width:8px;background:rgba(16,31,28,.1);-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-60824824]::-webkit-scrollbar-thumb{background-color:#101f1c59;background-clip:padding-box;min-height:28px;-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-60824824]::-webkit-scrollbar-thumb:hover{background-color:#101f1cd9}*[data-v-60824824]{scrollbar-color:#e5e5e5 #f7f7f9;scrollbar-width:thin}.full-width-input[data-v-60824824]{width:100%!important}.auto-full-width[data-v-60824824]{width:100%}.auto-full-width[data-v-60824824] .el-range-editor{width:100%!important}.primary-color[data-v-417e0c7c]{color:#409eff}.background-opacity[data-v-417e0c7c]{background:rgba(64,158,255,.6)}.form-widget-list .ghost[data-v-417e0c7c]{content:"";font-size:0;height:3px;box-sizing:border-box;background:#409EFF;border:2px solid #409EFF;outline-width:0;padding:0;overflow:hidden}.el-form-item .el-rate[data-v-417e0c7c]{margin-top:8px}.el-form-item--medium .el-radio[data-v-417e0c7c]{line-height:36px!important}.el-form-item--medium .el-rate[data-v-417e0c7c]{margin-top:8px}.el-form-item--small .el-radio[data-v-417e0c7c]{line-height:32px!important}.el-form-item--small .el-rate[data-v-417e0c7c]{margin-top:6px}.el-form-item--mini .el-radio[data-v-417e0c7c]{line-height:28px!important}.el-form-item--mini .el-rate[data-v-417e0c7c]{margin-top:4px}.el-card[data-v-417e0c7c]{margin-top:3px;margin-bottom:3px}input[type=password][data-v-417e0c7c]::-ms-reveal{display:none}.auto-full-width.el-date-editor.el-input[data-v-417e0c7c],.auto-full-width.el-date-editor.el-input__inner[data-v-417e0c7c]{width:100%!important}[data-v-417e0c7c]::-webkit-scrollbar{width:8px;height:8px}[data-v-417e0c7c]::-webkit-scrollbar-track{width:8px;background:rgba(16,31,28,.1);-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-417e0c7c]::-webkit-scrollbar-thumb{background-color:#101f1c59;background-clip:padding-box;min-height:28px;-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-417e0c7c]::-webkit-scrollbar-thumb:hover{background-color:#101f1cd9}*[data-v-417e0c7c]{scrollbar-color:#e5e5e5 #f7f7f9;scrollbar-width:thin}.full-width-input[data-v-417e0c7c]{width:100%!important}.primary-color[data-v-9332ab84]{color:#409eff}.background-opacity[data-v-9332ab84]{background:rgba(64,158,255,.6)}.form-widget-list .ghost[data-v-9332ab84]{content:"";font-size:0;height:3px;box-sizing:border-box;background:#409EFF;border:2px solid #409EFF;outline-width:0;padding:0;overflow:hidden}.el-form-item .el-rate[data-v-9332ab84]{margin-top:8px}.el-form-item--medium .el-radio[data-v-9332ab84]{line-height:36px!important}.el-form-item--medium .el-rate[data-v-9332ab84]{margin-top:8px}.el-form-item--small .el-radio[data-v-9332ab84]{line-height:32px!important}.el-form-item--small .el-rate[data-v-9332ab84]{margin-top:6px}.el-form-item--mini .el-radio[data-v-9332ab84]{line-height:28px!important}.el-form-item--mini .el-rate[data-v-9332ab84]{margin-top:4px}.el-card[data-v-9332ab84]{margin-top:3px;margin-bottom:3px}input[type=password][data-v-9332ab84]::-ms-reveal{display:none}.auto-full-width.el-date-editor.el-input[data-v-9332ab84],.auto-full-width.el-date-editor.el-input__inner[data-v-9332ab84]{width:100%!important}[data-v-9332ab84]::-webkit-scrollbar{width:8px;height:8px}[data-v-9332ab84]::-webkit-scrollbar-track{width:8px;background:rgba(16,31,28,.1);-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-9332ab84]::-webkit-scrollbar-thumb{background-color:#101f1c59;background-clip:padding-box;min-height:28px;-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-9332ab84]::-webkit-scrollbar-thumb:hover{background-color:#101f1cd9}*[data-v-9332ab84]{scrollbar-color:#e5e5e5 #f7f7f9;scrollbar-width:thin}.blank-cell[data-v-9332ab84]{font-style:italic;color:#ccc}.blank-cell span.invisible-content[data-v-9332ab84]{opacity:0}.primary-color[data-v-2eb559e6]{color:#409eff}.background-opacity[data-v-2eb559e6]{background:rgba(64,158,255,.6)}.form-widget-list .ghost[data-v-2eb559e6]{content:"";font-size:0;height:3px;box-sizing:border-box;background:#409EFF;border:2px solid #409EFF;outline-width:0;padding:0;overflow:hidden}.el-form-item .el-rate[data-v-2eb559e6]{margin-top:8px}.el-form-item--medium .el-radio[data-v-2eb559e6]{line-height:36px!important}.el-form-item--medium .el-rate[data-v-2eb559e6]{margin-top:8px}.el-form-item--small .el-radio[data-v-2eb559e6]{line-height:32px!important}.el-form-item--small .el-rate[data-v-2eb559e6]{margin-top:6px}.el-form-item--mini .el-radio[data-v-2eb559e6]{line-height:28px!important}.el-form-item--mini .el-rate[data-v-2eb559e6]{margin-top:4px}.el-card[data-v-2eb559e6]{margin-top:3px;margin-bottom:3px}input[type=password][data-v-2eb559e6]::-ms-reveal{display:none}.auto-full-width.el-date-editor.el-input[data-v-2eb559e6],.auto-full-width.el-date-editor.el-input__inner[data-v-2eb559e6]{width:100%!important}[data-v-2eb559e6]::-webkit-scrollbar{width:8px;height:8px}[data-v-2eb559e6]::-webkit-scrollbar-track{width:8px;background:rgba(16,31,28,.1);-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-2eb559e6]::-webkit-scrollbar-thumb{background-color:#101f1c59;background-clip:padding-box;min-height:28px;-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-2eb559e6]::-webkit-scrollbar-thumb:hover{background-color:#101f1cd9}*[data-v-2eb559e6]{scrollbar-color:#e5e5e5 #f7f7f9;scrollbar-width:thin}.sub-form-container[data-v-2eb559e6]{margin-bottom:8px;text-align:left}.sub-form-container[data-v-2eb559e6] .el-row.header-row{padding-bottom:0}.sub-form-container[data-v-2eb559e6] .el-row.sub-form-row{padding-top:3px;padding-bottom:3px}.sub-form-container[data-v-2eb559e6] .el-row.sub-form-row .row-number-span{margin-left:16px}div.action-header-column[data-v-2eb559e6]{display:inline-block;width:120px}div.action-header-column .action-label[data-v-2eb559e6]{margin-right:12px}div.action-header-column .action-button[data-v-2eb559e6]{padding-left:8px;padding-right:8px}div.field-header-column[data-v-2eb559e6]{display:inline-block}div.field-header-column span.custom-label i[data-v-2eb559e6]{margin:0 3px}div.field-header-column.is-required[data-v-2eb559e6]:before{content:"*";color:#f56c6c;margin-right:4px}div.label-center-left[data-v-2eb559e6]{text-align:left}div.label-center-align[data-v-2eb559e6]{text-align:center}div.label-right-align[data-v-2eb559e6]{text-align:right}div.sub-form-action-column[data-v-2eb559e6]{display:inline-block;width:120px}div.sub-form-action-column[data-v-2eb559e6] .el-form-item{margin-bottom:0}div.sub-form-action-column[data-v-2eb559e6] .el-button{font-size:14px;padding:0;background:#DCDFE6;border:4px solid #DCDFE6}div.sub-form-action-column.hide-label[data-v-2eb559e6] .el-form-item__label{display:none}div.sub-form-table-column[data-v-2eb559e6]{display:inline-block}div.sub-form-table-column[data-v-2eb559e6] .el-form-item{margin-left:4px;margin-right:4px;margin-bottom:0}div.sub-form-table-column[data-v-2eb559e6] .el-form-item__content{margin-left:0!important}div.sub-form-table-column.hide-label[data-v-2eb559e6] .el-form-item__label{display:none}.primary-color[data-v-1825ed0b]{color:#409eff}.background-opacity[data-v-1825ed0b]{background:rgba(64,158,255,.6)}.form-widget-list .ghost[data-v-1825ed0b]{content:"";font-size:0;height:3px;box-sizing:border-box;background:#409EFF;border:2px solid #409EFF;outline-width:0;padding:0;overflow:hidden}.el-form-item .el-rate[data-v-1825ed0b]{margin-top:8px}.el-form-item--medium .el-radio[data-v-1825ed0b]{line-height:36px!important}.el-form-item--medium .el-rate[data-v-1825ed0b]{margin-top:8px}.el-form-item--small .el-radio[data-v-1825ed0b]{line-height:32px!important}.el-form-item--small .el-rate[data-v-1825ed0b]{margin-top:6px}.el-form-item--mini .el-radio[data-v-1825ed0b]{line-height:28px!important}.el-form-item--mini .el-rate[data-v-1825ed0b]{margin-top:4px}.el-card[data-v-1825ed0b]{margin-top:3px;margin-bottom:3px}input[type=password][data-v-1825ed0b]::-ms-reveal{display:none}.auto-full-width.el-date-editor.el-input[data-v-1825ed0b],.auto-full-width.el-date-editor.el-input__inner[data-v-1825ed0b]{width:100%!important}[data-v-1825ed0b]::-webkit-scrollbar{width:8px;height:8px}[data-v-1825ed0b]::-webkit-scrollbar-track{width:8px;background:rgba(16,31,28,.1);-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-1825ed0b]::-webkit-scrollbar-thumb{background-color:#101f1c59;background-clip:padding-box;min-height:28px;-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-1825ed0b]::-webkit-scrollbar-thumb:hover{background-color:#101f1cd9}*[data-v-1825ed0b]{scrollbar-color:#e5e5e5 #f7f7f9;scrollbar-width:thin}td.table-cell[data-v-1825ed0b]{display:table-cell;height:36px;border:1px solid #e5e5e5}.primary-color[data-v-dfc6ca8e]{color:#409eff}.background-opacity[data-v-dfc6ca8e]{background:rgba(64,158,255,.6)}.form-widget-list .ghost[data-v-dfc6ca8e]{content:"";font-size:0;height:3px;box-sizing:border-box;background:#409EFF;border:2px solid #409EFF;outline-width:0;padding:0;overflow:hidden}.el-form-item .el-rate[data-v-dfc6ca8e]{margin-top:8px}.el-form-item--medium .el-radio[data-v-dfc6ca8e]{line-height:36px!important}.el-form-item--medium .el-rate[data-v-dfc6ca8e]{margin-top:8px}.el-form-item--small .el-radio[data-v-dfc6ca8e]{line-height:32px!important}.el-form-item--small .el-rate[data-v-dfc6ca8e]{margin-top:6px}.el-form-item--mini .el-radio[data-v-dfc6ca8e]{line-height:28px!important}.el-form-item--mini .el-rate[data-v-dfc6ca8e]{margin-top:4px}.el-card[data-v-dfc6ca8e]{margin-top:3px;margin-bottom:3px}input[type=password][data-v-dfc6ca8e]::-ms-reveal{display:none}.auto-full-width.el-date-editor.el-input[data-v-dfc6ca8e],.auto-full-width.el-date-editor.el-input__inner[data-v-dfc6ca8e]{width:100%!important}[data-v-dfc6ca8e]::-webkit-scrollbar{width:8px;height:8px}[data-v-dfc6ca8e]::-webkit-scrollbar-track{width:8px;background:rgba(16,31,28,.1);-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-dfc6ca8e]::-webkit-scrollbar-thumb{background-color:#101f1c59;background-clip:padding-box;min-height:28px;-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-dfc6ca8e]::-webkit-scrollbar-thumb:hover{background-color:#101f1cd9}*[data-v-dfc6ca8e]{scrollbar-color:#e5e5e5 #f7f7f9;scrollbar-width:thin}div.table-container table.table-layout[data-v-dfc6ca8e]{width:100%;table-layout:fixed;border-collapse:collapse}.primary-color[data-v-544703a2]{color:#409eff}.background-opacity[data-v-544703a2]{background:rgba(64,158,255,.6)}.form-widget-list .ghost[data-v-544703a2]{content:"";font-size:0;height:3px;box-sizing:border-box;background:#409EFF;border:2px solid #409EFF;outline-width:0;padding:0;overflow:hidden}.el-form-item .el-rate[data-v-544703a2]{margin-top:8px}.el-form-item--medium .el-radio[data-v-544703a2]{line-height:36px!important}.el-form-item--medium .el-rate[data-v-544703a2]{margin-top:8px}.el-form-item--small .el-radio[data-v-544703a2]{line-height:32px!important}.el-form-item--small .el-rate[data-v-544703a2]{margin-top:6px}.el-form-item--mini .el-radio[data-v-544703a2]{line-height:28px!important}.el-form-item--mini .el-rate[data-v-544703a2]{margin-top:4px}.el-card[data-v-544703a2]{margin-top:3px;margin-bottom:3px}input[type=password][data-v-544703a2]::-ms-reveal{display:none}.auto-full-width.el-date-editor.el-input[data-v-544703a2],.auto-full-width.el-date-editor.el-input__inner[data-v-544703a2]{width:100%!important}[data-v-544703a2]::-webkit-scrollbar{width:8px;height:8px}[data-v-544703a2]::-webkit-scrollbar-track{width:8px;background:rgba(16,31,28,.1);-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-544703a2]::-webkit-scrollbar-thumb{background-color:#101f1c59;background-clip:padding-box;min-height:28px;-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-544703a2]::-webkit-scrollbar-thumb:hover{background-color:#101f1cd9}*[data-v-544703a2]{scrollbar-color:#e5e5e5 #f7f7f9;scrollbar-width:thin}.el-form[data-v-544703a2] .el-row{padding:8px}.primary-color[data-v-335e1214]{color:#409eff}.background-opacity[data-v-335e1214]{background:rgba(64,158,255,.6)}.form-widget-list .ghost[data-v-335e1214]{content:"";font-size:0;height:3px;box-sizing:border-box;background:#409EFF;border:2px solid #409EFF;outline-width:0;padding:0;overflow:hidden}.el-form-item .el-rate[data-v-335e1214]{margin-top:8px}.el-form-item--medium .el-radio[data-v-335e1214]{line-height:36px!important}.el-form-item--medium .el-rate[data-v-335e1214]{margin-top:8px}.el-form-item--small .el-radio[data-v-335e1214]{line-height:32px!important}.el-form-item--small .el-rate[data-v-335e1214]{margin-top:6px}.el-form-item--mini .el-radio[data-v-335e1214]{line-height:28px!important}.el-form-item--mini .el-rate[data-v-335e1214]{margin-top:4px}.el-card[data-v-335e1214]{margin-top:3px;margin-bottom:3px}input[type=password][data-v-335e1214]::-ms-reveal{display:none}.auto-full-width.el-date-editor.el-input[data-v-335e1214],.auto-full-width.el-date-editor.el-input__inner[data-v-335e1214]{width:100%!important}[data-v-335e1214]::-webkit-scrollbar{width:8px;height:8px}[data-v-335e1214]::-webkit-scrollbar-track{width:8px;background:rgba(16,31,28,.1);-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-335e1214]::-webkit-scrollbar-thumb{background-color:#101f1c59;background-clip:padding-box;min-height:28px;-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-335e1214]::-webkit-scrollbar-thumb:hover{background-color:#101f1cd9}*[data-v-335e1214]{scrollbar-color:#e5e5e5 #f7f7f9;scrollbar-width:thin}.ace-editor[data-v-335e1214]{min-height:300px}.primary-color[data-v-47957683]{color:#409eff}.background-opacity[data-v-47957683]{background:rgba(64,158,255,.6)}.form-widget-list .ghost[data-v-47957683]{content:"";font-size:0;height:3px;box-sizing:border-box;background:#409EFF;border:2px solid #409EFF;outline-width:0;padding:0;overflow:hidden}.el-form-item .el-rate[data-v-47957683]{margin-top:8px}.el-form-item--medium .el-radio[data-v-47957683]{line-height:36px!important}.el-form-item--medium .el-rate[data-v-47957683]{margin-top:8px}.el-form-item--small .el-radio[data-v-47957683]{line-height:32px!important}.el-form-item--small .el-rate[data-v-47957683]{margin-top:6px}.el-form-item--mini .el-radio[data-v-47957683]{line-height:28px!important}.el-form-item--mini .el-rate[data-v-47957683]{margin-top:4px}.el-card[data-v-47957683]{margin-top:3px;margin-bottom:3px}input[type=password][data-v-47957683]::-ms-reveal{display:none}.auto-full-width.el-date-editor.el-input[data-v-47957683],.auto-full-width.el-date-editor.el-input__inner[data-v-47957683]{width:100%!important}[data-v-47957683]::-webkit-scrollbar{width:8px;height:8px}[data-v-47957683]::-webkit-scrollbar-track{width:8px;background:rgba(16,31,28,.1);-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-47957683]::-webkit-scrollbar-thumb{background-color:#101f1c59;background-clip:padding-box;min-height:28px;-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-47957683]::-webkit-scrollbar-thumb:hover{background-color:#101f1cd9}*[data-v-47957683]{scrollbar-color:#e5e5e5 #f7f7f9;scrollbar-width:thin}.toolbar-container[data-v-47957683]:after{display:block;content:"";clear:both}.left-toolbar[data-v-47957683]{display:flex;margin-top:4px;float:left;font-size:16px}.right-toolbar[data-v-47957683]{display:flex;float:right;line-height:42px;text-align:right;overflow:hidden}.right-toolbar .right-toolbar-con[data-v-47957683]{text-align:left;width:600px}.right-toolbar[data-v-47957683] .el-button{margin-left:10px}.right-toolbar[data-v-47957683] .el-button--text{font-size:14px!important}.right-toolbar[data-v-47957683] .svg-icon{margin-left:0;margin-right:.05em}.el-button i[data-v-47957683]{margin-right:3px}.small-padding-dialog[data-v-47957683] .el-dialog__header{background:#f1f2f3}.small-padding-dialog[data-v-47957683] .el-dialog__body{padding:12px 15px}.small-padding-dialog[data-v-47957683] .el-dialog__body .el-alert.alert-padding{padding:0 10px}.small-padding-dialog[data-v-47957683] .ace-container{border:1px solid #DCDFE6}.dialog-title-light-bg[data-v-47957683] .el-dialog__header{background:#f1f2f3}.no-box-shadow[data-v-47957683]{box-shadow:none}.no-padding.el-tabs--border-card[data-v-47957683] .el-tabs__content{padding:0}.form-render-wrapper.h5-layout[data-v-47957683]{margin:0 auto;width:420px;border-radius:15px;box-shadow:0 0 1px 10px #495060;height:calc(100vh - 175px);overflow-y:auto;overflow-x:hidden}.form-render-wrapper.pad-layout[data-v-47957683]{margin:0 auto;width:960px;border-radius:15px;box-shadow:0 0 1px 10px #495060;height:calc(100vh - 175px);overflow-y:auto;overflow-x:hidden}.node-tree-drawer[data-v-47957683] .el-drawer{padding:10px;overflow:auto}.node-tree-drawer[data-v-47957683] .el-drawer__header{margin-bottom:12px;padding:5px 5px 0}.node-tree-drawer[data-v-47957683] .el-drawer__body{padding-left:5px}[data-v-47957683] .node-tree .el-tree-node{position:relative;padding-left:12px}[data-v-47957683] .node-tree .el-tree-node__content{padding-left:0!important}[data-v-47957683] .node-tree .el-tree-node__expand-icon.is-leaf{display:none}[data-v-47957683] .node-tree .el-tree-node__children{padding-left:12px;overflow:visible!important}[data-v-47957683] .node-tree .el-tree-node :last-child:before{height:38px}[data-v-47957683] .node-tree .el-tree>.el-tree-node:before{border-left:none}[data-v-47957683] .node-tree .el-tree>.el-tree-node:after{border-top:none}[data-v-47957683] .node-tree .el-tree-node:before{content:"";left:-4px;position:absolute;right:auto;border-width:1px}[data-v-47957683] .node-tree .el-tree-node:after{content:"";left:-4px;position:absolute;right:auto;border-width:1px}[data-v-47957683] .node-tree .el-tree-node:before{border-left:1px dashed #4386c6;bottom:0px;height:100%;top:-10px;width:1px}[data-v-47957683] .node-tree .el-tree-node:after{border-top:1px dashed #4386c6;height:20px;top:12px;width:16px}[data-v-47957683] .node-tree .el-tree-node.is-current>.el-tree-node__content{background:#c2d6ea!important}[data-v-47957683] .node-tree .el-tree-node__expand-icon{margin-left:-3px;padding:6px 6px 6px 0;font-size:16px}.primary-color[data-v-29a8e49b]{color:#409eff}.background-opacity[data-v-29a8e49b]{background:rgba(64,158,255,.6)}.form-widget-list .ghost[data-v-29a8e49b]{content:"";font-size:0;height:3px;box-sizing:border-box;background:#409EFF;border:2px solid #409EFF;outline-width:0;padding:0;overflow:hidden}.el-form-item .el-rate[data-v-29a8e49b]{margin-top:8px}.el-form-item--medium .el-radio[data-v-29a8e49b]{line-height:36px!important}.el-form-item--medium .el-rate[data-v-29a8e49b]{margin-top:8px}.el-form-item--small .el-radio[data-v-29a8e49b]{line-height:32px!important}.el-form-item--small .el-rate[data-v-29a8e49b]{margin-top:6px}.el-form-item--mini .el-radio[data-v-29a8e49b]{line-height:28px!important}.el-form-item--mini .el-rate[data-v-29a8e49b]{margin-top:4px}.el-card[data-v-29a8e49b]{margin-top:3px;margin-bottom:3px}input[type=password][data-v-29a8e49b]::-ms-reveal{display:none}.auto-full-width.el-date-editor.el-input[data-v-29a8e49b],.auto-full-width.el-date-editor.el-input__inner[data-v-29a8e49b]{width:100%!important}[data-v-29a8e49b]::-webkit-scrollbar{width:8px;height:8px}[data-v-29a8e49b]::-webkit-scrollbar-track{width:8px;background:rgba(16,31,28,.1);-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-29a8e49b]::-webkit-scrollbar-thumb{background-color:#101f1c59;background-clip:padding-box;min-height:28px;-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-29a8e49b]::-webkit-scrollbar-thumb:hover{background-color:#101f1cd9}*[data-v-29a8e49b]{scrollbar-color:#e5e5e5 #f7f7f9;scrollbar-width:thin}.radio-group-custom[data-v-29a8e49b] .el-radio-button__inner{padding-left:12px;padding-right:12px}.primary-color[data-v-7ce52f1e]{color:#409eff}.background-opacity[data-v-7ce52f1e]{background:rgba(64,158,255,.6)}.form-widget-list .ghost[data-v-7ce52f1e]{content:"";font-size:0;height:3px;box-sizing:border-box;background:#409EFF;border:2px solid #409EFF;outline-width:0;padding:0;overflow:hidden}.el-form-item .el-rate[data-v-7ce52f1e]{margin-top:8px}.el-form-item--medium .el-radio[data-v-7ce52f1e]{line-height:36px!important}.el-form-item--medium .el-rate[data-v-7ce52f1e]{margin-top:8px}.el-form-item--small .el-radio[data-v-7ce52f1e]{line-height:32px!important}.el-form-item--small .el-rate[data-v-7ce52f1e]{margin-top:6px}.el-form-item--mini .el-radio[data-v-7ce52f1e]{line-height:28px!important}.el-form-item--mini .el-rate[data-v-7ce52f1e]{margin-top:4px}.el-card[data-v-7ce52f1e]{margin-top:3px;margin-bottom:3px}input[type=password][data-v-7ce52f1e]::-ms-reveal{display:none}.auto-full-width.el-date-editor.el-input[data-v-7ce52f1e],.auto-full-width.el-date-editor.el-input__inner[data-v-7ce52f1e]{width:100%!important}[data-v-7ce52f1e]::-webkit-scrollbar{width:8px;height:8px}[data-v-7ce52f1e]::-webkit-scrollbar-track{width:8px;background:rgba(16,31,28,.1);-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-7ce52f1e]::-webkit-scrollbar-thumb{background-color:#101f1c59;background-clip:padding-box;min-height:28px;-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-7ce52f1e]::-webkit-scrollbar-thumb:hover{background-color:#101f1cd9}*[data-v-7ce52f1e]{scrollbar-color:#e5e5e5 #f7f7f9;scrollbar-width:thin}.option-items-pane[data-v-7ce52f1e]{width:100%}.option-items-pane ul[data-v-7ce52f1e]{padding-inline-start:6px;padding-left:6px}li.ghost[data-v-7ce52f1e]{background:#fff;border:2px dotted #409EFF}.drag-option[data-v-7ce52f1e]{cursor:move}.small-padding-dialog[data-v-7ce52f1e] .el-dialog__body{padding:10px 15px}.dialog-footer .el-button[data-v-7ce52f1e]{width:100px}.full-width-input[data-v-7ce52f1e],.full-width-input[data-v-7ce52f1e] .el-cascader{width:100%!important}.primary-color[data-v-a8b6d272]{color:#409eff}.background-opacity[data-v-a8b6d272]{background:rgba(64,158,255,.6)}.form-widget-list .ghost[data-v-a8b6d272]{content:"";font-size:0;height:3px;box-sizing:border-box;background:#409EFF;border:2px solid #409EFF;outline-width:0;padding:0;overflow:hidden}.el-form-item .el-rate[data-v-a8b6d272]{margin-top:8px}.el-form-item--medium .el-radio[data-v-a8b6d272]{line-height:36px!important}.el-form-item--medium .el-rate[data-v-a8b6d272]{margin-top:8px}.el-form-item--small .el-radio[data-v-a8b6d272]{line-height:32px!important}.el-form-item--small .el-rate[data-v-a8b6d272]{margin-top:6px}.el-form-item--mini .el-radio[data-v-a8b6d272]{line-height:28px!important}.el-form-item--mini .el-rate[data-v-a8b6d272]{margin-top:4px}.el-card[data-v-a8b6d272]{margin-top:3px;margin-bottom:3px}input[type=password][data-v-a8b6d272]::-ms-reveal{display:none}.auto-full-width.el-date-editor.el-input[data-v-a8b6d272],.auto-full-width.el-date-editor.el-input__inner[data-v-a8b6d272]{width:100%!important}[data-v-a8b6d272]::-webkit-scrollbar{width:8px;height:8px}[data-v-a8b6d272]::-webkit-scrollbar-track{width:8px;background:rgba(16,31,28,.1);-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-a8b6d272]::-webkit-scrollbar-thumb{background-color:#101f1c59;background-clip:padding-box;min-height:28px;-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-a8b6d272]::-webkit-scrollbar-thumb:hover{background-color:#101f1cd9}*[data-v-a8b6d272]{scrollbar-color:#e5e5e5 #f7f7f9;scrollbar-width:thin}.radio-group-custom[data-v-a8b6d272] .el-radio-button__inner{padding-left:12px;padding-right:12px}.primary-color[data-v-5998270e]{color:#409eff}.background-opacity[data-v-5998270e]{background:rgba(64,158,255,.6)}.form-widget-list .ghost[data-v-5998270e]{content:"";font-size:0;height:3px;box-sizing:border-box;background:#409EFF;border:2px solid #409EFF;outline-width:0;padding:0;overflow:hidden}.el-form-item .el-rate[data-v-5998270e]{margin-top:8px}.el-form-item--medium .el-radio[data-v-5998270e]{line-height:36px!important}.el-form-item--medium .el-rate[data-v-5998270e]{margin-top:8px}.el-form-item--small .el-radio[data-v-5998270e]{line-height:32px!important}.el-form-item--small .el-rate[data-v-5998270e]{margin-top:6px}.el-form-item--mini .el-radio[data-v-5998270e]{line-height:28px!important}.el-form-item--mini .el-rate[data-v-5998270e]{margin-top:4px}.el-card[data-v-5998270e]{margin-top:3px;margin-bottom:3px}input[type=password][data-v-5998270e]::-ms-reveal{display:none}.auto-full-width.el-date-editor.el-input[data-v-5998270e],.auto-full-width.el-date-editor.el-input__inner[data-v-5998270e]{width:100%!important}[data-v-5998270e]::-webkit-scrollbar{width:8px;height:8px}[data-v-5998270e]::-webkit-scrollbar-track{width:8px;background:rgba(16,31,28,.1);-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-5998270e]::-webkit-scrollbar-thumb{background-color:#101f1c59;background-clip:padding-box;min-height:28px;-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-5998270e]::-webkit-scrollbar-thumb:hover{background-color:#101f1cd9}*[data-v-5998270e]{scrollbar-color:#e5e5e5 #f7f7f9;scrollbar-width:thin}li.col-item[data-v-5998270e]{list-style:none}li.col-item span.col-span-title[data-v-5998270e]{display:inline-block;font-size:13px;width:120px}li.col-item .col-delete-button[data-v-5998270e]{margin-left:6px}.primary-color[data-v-baeda47c]{color:#409eff}.background-opacity[data-v-baeda47c]{background:rgba(64,158,255,.6)}.form-widget-list .ghost[data-v-baeda47c]{content:"";font-size:0;height:3px;box-sizing:border-box;background:#409EFF;border:2px solid #409EFF;outline-width:0;padding:0;overflow:hidden}.el-form-item .el-rate[data-v-baeda47c]{margin-top:8px}.el-form-item--medium .el-radio[data-v-baeda47c]{line-height:36px!important}.el-form-item--medium .el-rate[data-v-baeda47c]{margin-top:8px}.el-form-item--small .el-radio[data-v-baeda47c]{line-height:32px!important}.el-form-item--small .el-rate[data-v-baeda47c]{margin-top:6px}.el-form-item--mini .el-radio[data-v-baeda47c]{line-height:28px!important}.el-form-item--mini .el-rate[data-v-baeda47c]{margin-top:4px}.el-card[data-v-baeda47c]{margin-top:3px;margin-bottom:3px}input[type=password][data-v-baeda47c]::-ms-reveal{display:none}.auto-full-width.el-date-editor.el-input[data-v-baeda47c],.auto-full-width.el-date-editor.el-input__inner[data-v-baeda47c]{width:100%!important}[data-v-baeda47c]::-webkit-scrollbar{width:8px;height:8px}[data-v-baeda47c]::-webkit-scrollbar-track{width:8px;background:rgba(16,31,28,.1);-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-baeda47c]::-webkit-scrollbar-thumb{background-color:#101f1c59;background-clip:padding-box;min-height:28px;-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-baeda47c]::-webkit-scrollbar-thumb:hover{background-color:#101f1cd9}*[data-v-baeda47c]{scrollbar-color:#e5e5e5 #f7f7f9;scrollbar-width:thin}.radio-group-custom[data-v-baeda47c] .el-radio-button__inner{padding-left:12px;padding-right:12px}.primary-color[data-v-ecb4857e]{color:#409eff}.background-opacity[data-v-ecb4857e]{background:rgba(64,158,255,.6)}.form-widget-list .ghost[data-v-ecb4857e]{content:"";font-size:0;height:3px;box-sizing:border-box;background:#409EFF;border:2px solid #409EFF;outline-width:0;padding:0;overflow:hidden}.el-form-item .el-rate[data-v-ecb4857e]{margin-top:8px}.el-form-item--medium .el-radio[data-v-ecb4857e]{line-height:36px!important}.el-form-item--medium .el-rate[data-v-ecb4857e]{margin-top:8px}.el-form-item--small .el-radio[data-v-ecb4857e]{line-height:32px!important}.el-form-item--small .el-rate[data-v-ecb4857e]{margin-top:6px}.el-form-item--mini .el-radio[data-v-ecb4857e]{line-height:28px!important}.el-form-item--mini .el-rate[data-v-ecb4857e]{margin-top:4px}.el-card[data-v-ecb4857e]{margin-top:3px;margin-bottom:3px}input[type=password][data-v-ecb4857e]::-ms-reveal{display:none}.auto-full-width.el-date-editor.el-input[data-v-ecb4857e],.auto-full-width.el-date-editor.el-input__inner[data-v-ecb4857e]{width:100%!important}[data-v-ecb4857e]::-webkit-scrollbar{width:8px;height:8px}[data-v-ecb4857e]::-webkit-scrollbar-track{width:8px;background:rgba(16,31,28,.1);-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-ecb4857e]::-webkit-scrollbar-thumb{background-color:#101f1c59;background-clip:padding-box;min-height:28px;-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-ecb4857e]::-webkit-scrollbar-thumb:hover{background-color:#101f1cd9}*[data-v-ecb4857e]{scrollbar-color:#e5e5e5 #f7f7f9;scrollbar-width:thin}li.col-item[data-v-ecb4857e]{list-style:none}li.col-item span.col-span-title[data-v-ecb4857e]{display:inline-block;font-size:13px;width:120px}li.col-item .col-delete-button[data-v-ecb4857e]{margin-left:6px}.panes-setting ul[data-v-ecb4857e]{padding-inline-start:0;padding-left:0;margin:0}.panes-setting .drag-option[data-v-ecb4857e]{cursor:move}.panes-setting li.ghost[data-v-ecb4857e]{background:#fff;border:2px dotted #409EFF}.html-content-editor[data-v-a8d84c8e]{font-size:13px}.primary-color[data-v-d134b7b8]{color:#409eff}.background-opacity[data-v-d134b7b8]{background:rgba(64,158,255,.6)}.form-widget-list .ghost[data-v-d134b7b8]{content:"";font-size:0;height:3px;box-sizing:border-box;background:#409EFF;border:2px solid #409EFF;outline-width:0;padding:0;overflow:hidden}.el-form-item .el-rate[data-v-d134b7b8]{margin-top:8px}.el-form-item--medium .el-radio[data-v-d134b7b8]{line-height:36px!important}.el-form-item--medium .el-rate[data-v-d134b7b8]{margin-top:8px}.el-form-item--small .el-radio[data-v-d134b7b8]{line-height:32px!important}.el-form-item--small .el-rate[data-v-d134b7b8]{margin-top:6px}.el-form-item--mini .el-radio[data-v-d134b7b8]{line-height:28px!important}.el-form-item--mini .el-rate[data-v-d134b7b8]{margin-top:4px}.el-card[data-v-d134b7b8]{margin-top:3px;margin-bottom:3px}input[type=password][data-v-d134b7b8]::-ms-reveal{display:none}.auto-full-width.el-date-editor.el-input[data-v-d134b7b8],.auto-full-width.el-date-editor.el-input__inner[data-v-d134b7b8]{width:100%!important}[data-v-d134b7b8]::-webkit-scrollbar{width:8px;height:8px}[data-v-d134b7b8]::-webkit-scrollbar-track{width:8px;background:rgba(16,31,28,.1);-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-d134b7b8]::-webkit-scrollbar-thumb{background-color:#101f1c59;background-clip:padding-box;min-height:28px;-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-d134b7b8]::-webkit-scrollbar-thumb:hover{background-color:#101f1cd9}*[data-v-d134b7b8]{scrollbar-color:#e5e5e5 #f7f7f9;scrollbar-width:thin}.setting-form[data-v-d134b7b8] .el-form-item__label{font-size:13px;overflow:hidden;white-space:nowrap}.setting-form[data-v-d134b7b8] .el-form-item--small.el-form-item{margin-bottom:10px}.setting-form .radio-group-custom[data-v-d134b7b8] .el-radio-button__inner{padding-left:12px;padding-right:12px}.setting-form .custom-divider.el-divider--horizontal[data-v-d134b7b8]{margin:10px 0}.setting-collapse[data-v-d134b7b8] .el-collapse-item__content{padding-bottom:6px}.setting-collapse[data-v-d134b7b8] .el-collapse-item__header{font-style:italic;font-weight:700}.small-padding-dialog[data-v-d134b7b8] .el-dialog__body{padding:6px 15px 12px}.primary-color[data-v-458006ba]{color:#409eff}.background-opacity[data-v-458006ba]{background:rgba(64,158,255,.6)}.form-widget-list .ghost[data-v-458006ba]{content:"";font-size:0;height:3px;box-sizing:border-box;background:#409EFF;border:2px solid #409EFF;outline-width:0;padding:0;overflow:hidden}.el-form-item .el-rate[data-v-458006ba]{margin-top:8px}.el-form-item--medium .el-radio[data-v-458006ba]{line-height:36px!important}.el-form-item--medium .el-rate[data-v-458006ba]{margin-top:8px}.el-form-item--small .el-radio[data-v-458006ba]{line-height:32px!important}.el-form-item--small .el-rate[data-v-458006ba]{margin-top:6px}.el-form-item--mini .el-radio[data-v-458006ba]{line-height:28px!important}.el-form-item--mini .el-rate[data-v-458006ba]{margin-top:4px}.el-card[data-v-458006ba]{margin-top:3px;margin-bottom:3px}input[type=password][data-v-458006ba]::-ms-reveal{display:none}.auto-full-width.el-date-editor.el-input[data-v-458006ba],.auto-full-width.el-date-editor.el-input__inner[data-v-458006ba]{width:100%!important}[data-v-458006ba]::-webkit-scrollbar{width:8px;height:8px}[data-v-458006ba]::-webkit-scrollbar-track{width:8px;background:rgba(16,31,28,.1);-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-458006ba]::-webkit-scrollbar-thumb{background-color:#101f1c59;background-clip:padding-box;min-height:28px;-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-458006ba]::-webkit-scrollbar-thumb:hover{background-color:#101f1cd9}*[data-v-458006ba]{scrollbar-color:#e5e5e5 #f7f7f9;scrollbar-width:thin}.panel-container[data-v-458006ba]{padding:0 8px}.setting-scrollbar[data-v-458006ba] .el-scrollbar__wrap{overflow-x:hidden}.setting-collapse[data-v-458006ba] .el-collapse-item__content{padding-bottom:6px}.setting-collapse[data-v-458006ba] .el-collapse-item__header{font-style:italic;font-weight:700}.setting-form[data-v-458006ba] .el-form-item__label{font-size:13px;overflow:hidden;white-space:nowrap}.setting-form[data-v-458006ba] .el-form-item--small.el-form-item{margin-bottom:10px}[data-v-458006ba] .hide-spin-button input::-webkit-outer-spin-button,[data-v-458006ba] .hide-spin-button input::-webkit-inner-spin-button{-webkit-appearance:none!important}[data-v-458006ba] .hide-spin-button input[type=number]{-moz-appearance:textfield}[data-v-458006ba] .custom-divider.el-divider--horizontal{margin:10px 0}[data-v-458006ba] .custom-divider-margin-top.el-divider--horizontal{margin:20px 0}.small-padding-dialog[data-v-458006ba] .el-dialog__body{padding:6px 15px 12px}.primary-color[data-v-679de05a]{color:#409eff}.background-opacity[data-v-679de05a]{background:rgba(64,158,255,.6)}.form-widget-list .ghost[data-v-679de05a]{content:"";font-size:0;height:3px;box-sizing:border-box;background:#409EFF;border:2px solid #409EFF;outline-width:0;padding:0;overflow:hidden}.el-form-item .el-rate[data-v-679de05a]{margin-top:8px}.el-form-item--medium .el-radio[data-v-679de05a]{line-height:36px!important}.el-form-item--medium .el-rate[data-v-679de05a]{margin-top:8px}.el-form-item--small .el-radio[data-v-679de05a]{line-height:32px!important}.el-form-item--small .el-rate[data-v-679de05a]{margin-top:6px}.el-form-item--mini .el-radio[data-v-679de05a]{line-height:28px!important}.el-form-item--mini .el-rate[data-v-679de05a]{margin-top:4px}.el-card[data-v-679de05a]{margin-top:3px;margin-bottom:3px}input[type=password][data-v-679de05a]::-ms-reveal{display:none}.auto-full-width.el-date-editor.el-input[data-v-679de05a],.auto-full-width.el-date-editor.el-input__inner[data-v-679de05a]{width:100%!important}[data-v-679de05a]::-webkit-scrollbar{width:8px;height:8px}[data-v-679de05a]::-webkit-scrollbar-track{width:8px;background:rgba(16,31,28,.1);-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-679de05a]::-webkit-scrollbar-thumb{background-color:#101f1c59;background-clip:padding-box;min-height:28px;-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-679de05a]::-webkit-scrollbar-thumb:hover{background-color:#101f1cd9}*[data-v-679de05a]{scrollbar-color:#e5e5e5 #f7f7f9;scrollbar-width:thin}.container-wrapper[data-v-679de05a]{position:relative;margin-bottom:5px}.container-wrapper .container-action[data-v-679de05a]{position:absolute;bottom:0;right:-2px;height:28px;line-height:28px;background:#409EFF;z-index:999}.container-wrapper .container-action i[data-v-679de05a]{font-size:14px;color:#fff;margin:0 5px;cursor:pointer}.container-wrapper .drag-handler[data-v-679de05a]{position:absolute;top:-2px;left:-2px;height:22px;line-height:22px;background:#409EFF;z-index:9}.container-wrapper .drag-handler i[data-v-679de05a]{font-size:14px;font-style:normal;color:#fff;margin:4px;cursor:move}.container-action[data-v-679de05a] .svg-icon,.drag-handler[data-v-679de05a] .svg-icon{margin-left:.1em;margin-right:.1em}.primary-color[data-v-130c31d3]{color:#409eff}.background-opacity[data-v-130c31d3]{background:rgba(64,158,255,.6)}.form-widget-list .ghost[data-v-130c31d3]{content:"";font-size:0;height:3px;box-sizing:border-box;background:#409EFF;border:2px solid #409EFF;outline-width:0;padding:0;overflow:hidden}.el-form-item .el-rate[data-v-130c31d3]{margin-top:8px}.el-form-item--medium .el-radio[data-v-130c31d3]{line-height:36px!important}.el-form-item--medium .el-rate[data-v-130c31d3]{margin-top:8px}.el-form-item--small .el-radio[data-v-130c31d3]{line-height:32px!important}.el-form-item--small .el-rate[data-v-130c31d3]{margin-top:6px}.el-form-item--mini .el-radio[data-v-130c31d3]{line-height:28px!important}.el-form-item--mini .el-rate[data-v-130c31d3]{margin-top:4px}.el-card[data-v-130c31d3]{margin-top:3px;margin-bottom:3px}input[type=password][data-v-130c31d3]::-ms-reveal{display:none}.auto-full-width.el-date-editor.el-input[data-v-130c31d3],.auto-full-width.el-date-editor.el-input__inner[data-v-130c31d3]{width:100%!important}[data-v-130c31d3]::-webkit-scrollbar{width:8px;height:8px}[data-v-130c31d3]::-webkit-scrollbar-track{width:8px;background:rgba(16,31,28,.1);-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-130c31d3]::-webkit-scrollbar-thumb{background-color:#101f1c59;background-clip:padding-box;min-height:28px;-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-130c31d3]::-webkit-scrollbar-thumb:hover{background-color:#101f1cd9}*[data-v-130c31d3]{scrollbar-color:#e5e5e5 #f7f7f9;scrollbar-width:thin}.grid-cell[data-v-130c31d3]{min-height:38px!important;padding:3px;outline:1px dashed #336699;position:relative}.grid-cell .form-widget-list[data-v-130c31d3]{min-height:28px}.grid-cell .grid-col-action[data-v-130c31d3]{position:absolute;bottom:0;right:-2px;height:28px;line-height:28px;background:#409EFF;z-index:999}.grid-cell .grid-col-action i[data-v-130c31d3]{font-size:14px;color:#fff;margin:0 5px;cursor:pointer}.grid-cell .grid-col-handler[data-v-130c31d3]{position:absolute;top:-2px;left:-2px;height:22px;line-height:22px;background:#409EFF;z-index:9}.grid-cell .grid-col-handler i[data-v-130c31d3]{font-size:14px;font-style:normal;color:#fff;margin:4px;cursor:default}.grid-col-action[data-v-130c31d3] .svg-icon,.grid-col-handler[data-v-130c31d3] .svg-icon{margin-left:.1em;margin-right:.1em}.primary-color[data-v-2b4f7bb7]{color:#409eff}.background-opacity[data-v-2b4f7bb7]{background:rgba(64,158,255,.6)}.form-widget-list .ghost[data-v-2b4f7bb7]{content:"";font-size:0;height:3px;box-sizing:border-box;background:#409EFF;border:2px solid #409EFF;outline-width:0;padding:0;overflow:hidden}.el-form-item .el-rate[data-v-2b4f7bb7]{margin-top:8px}.el-form-item--medium .el-radio[data-v-2b4f7bb7]{line-height:36px!important}.el-form-item--medium .el-rate[data-v-2b4f7bb7]{margin-top:8px}.el-form-item--small .el-radio[data-v-2b4f7bb7]{line-height:32px!important}.el-form-item--small .el-rate[data-v-2b4f7bb7]{margin-top:6px}.el-form-item--mini .el-radio[data-v-2b4f7bb7]{line-height:28px!important}.el-form-item--mini .el-rate[data-v-2b4f7bb7]{margin-top:4px}.el-card[data-v-2b4f7bb7]{margin-top:3px;margin-bottom:3px}input[type=password][data-v-2b4f7bb7]::-ms-reveal{display:none}.auto-full-width.el-date-editor.el-input[data-v-2b4f7bb7],.auto-full-width.el-date-editor.el-input__inner[data-v-2b4f7bb7]{width:100%!important}[data-v-2b4f7bb7]::-webkit-scrollbar{width:8px;height:8px}[data-v-2b4f7bb7]::-webkit-scrollbar-track{width:8px;background:rgba(16,31,28,.1);-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-2b4f7bb7]::-webkit-scrollbar-thumb{background-color:#101f1c59;background-clip:padding-box;min-height:28px;-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-2b4f7bb7]::-webkit-scrollbar-thumb:hover{background-color:#101f1cd9}*[data-v-2b4f7bb7]{scrollbar-color:#e5e5e5 #f7f7f9;scrollbar-width:thin}.el-row.grid-container[data-v-2b4f7bb7]{min-height:50px;outline:1px dashed #336699}.el-row.grid-container .form-widget-list[data-v-2b4f7bb7]{min-height:28px}.grid-container.selected[data-v-2b4f7bb7],.grid-cell.selected[data-v-2b4f7bb7]{outline:2px solid #409EFF!important}.primary-color[data-v-2c29f864]{color:#409eff}.background-opacity[data-v-2c29f864]{background:rgba(64,158,255,.6)}.form-widget-list .ghost[data-v-2c29f864]{content:"";font-size:0;height:3px;box-sizing:border-box;background:#409EFF;border:2px solid #409EFF;outline-width:0;padding:0;overflow:hidden}.el-form-item .el-rate[data-v-2c29f864]{margin-top:8px}.el-form-item--medium .el-radio[data-v-2c29f864]{line-height:36px!important}.el-form-item--medium .el-rate[data-v-2c29f864]{margin-top:8px}.el-form-item--small .el-radio[data-v-2c29f864]{line-height:32px!important}.el-form-item--small .el-rate[data-v-2c29f864]{margin-top:6px}.el-form-item--mini .el-radio[data-v-2c29f864]{line-height:28px!important}.el-form-item--mini .el-rate[data-v-2c29f864]{margin-top:4px}.el-card[data-v-2c29f864]{margin-top:3px;margin-bottom:3px}input[type=password][data-v-2c29f864]::-ms-reveal{display:none}.auto-full-width.el-date-editor.el-input[data-v-2c29f864],.auto-full-width.el-date-editor.el-input__inner[data-v-2c29f864]{width:100%!important}[data-v-2c29f864]::-webkit-scrollbar{width:8px;height:8px}[data-v-2c29f864]::-webkit-scrollbar-track{width:8px;background:rgba(16,31,28,.1);-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-2c29f864]::-webkit-scrollbar-thumb{background-color:#101f1c59;background-clip:padding-box;min-height:28px;-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-2c29f864]::-webkit-scrollbar-thumb:hover{background-color:#101f1cd9}*[data-v-2c29f864]{scrollbar-color:#e5e5e5 #f7f7f9;scrollbar-width:thin}.tab-container[data-v-2c29f864]{margin:2px}.tab-container .form-widget-list[data-v-2c29f864],.tab-container[data-v-2c29f864] .el-tabs__content{min-height:28px}.tab-container.selected[data-v-2c29f864]{outline:2px solid #409EFF!important}.primary-color[data-v-2dc3e6c7]{color:#409eff}.background-opacity[data-v-2dc3e6c7]{background:rgba(64,158,255,.6)}.form-widget-list .ghost[data-v-2dc3e6c7]{content:"";font-size:0;height:3px;box-sizing:border-box;background:#409EFF;border:2px solid #409EFF;outline-width:0;padding:0;overflow:hidden}.el-form-item .el-rate[data-v-2dc3e6c7]{margin-top:8px}.el-form-item--medium .el-radio[data-v-2dc3e6c7]{line-height:36px!important}.el-form-item--medium .el-rate[data-v-2dc3e6c7]{margin-top:8px}.el-form-item--small .el-radio[data-v-2dc3e6c7]{line-height:32px!important}.el-form-item--small .el-rate[data-v-2dc3e6c7]{margin-top:6px}.el-form-item--mini .el-radio[data-v-2dc3e6c7]{line-height:28px!important}.el-form-item--mini .el-rate[data-v-2dc3e6c7]{margin-top:4px}.el-card[data-v-2dc3e6c7]{margin-top:3px;margin-bottom:3px}input[type=password][data-v-2dc3e6c7]::-ms-reveal{display:none}.auto-full-width.el-date-editor.el-input[data-v-2dc3e6c7],.auto-full-width.el-date-editor.el-input__inner[data-v-2dc3e6c7]{width:100%!important}[data-v-2dc3e6c7]::-webkit-scrollbar{width:8px;height:8px}[data-v-2dc3e6c7]::-webkit-scrollbar-track{width:8px;background:rgba(16,31,28,.1);-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-2dc3e6c7]::-webkit-scrollbar-thumb{background-color:#101f1c59;background-clip:padding-box;min-height:28px;-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-2dc3e6c7]::-webkit-scrollbar-thumb:hover{background-color:#101f1cd9}*[data-v-2dc3e6c7]{scrollbar-color:#e5e5e5 #f7f7f9;scrollbar-width:thin}.table-cell[data-v-2dc3e6c7]{border:1px dashed #336699;display:table-cell;position:relative}.table-cell .draggable-div[data-v-2dc3e6c7]{position:relative;height:100%}.table-cell .form-widget-list[data-v-2dc3e6c7]{border:1px dashed #336699;margin:3px;min-height:28px}.table-cell .table-cell-action[data-v-2dc3e6c7]{position:absolute;bottom:0;right:-2px;height:28px;line-height:28px;background:#409EFF;z-index:999;display:flex;align-items:center}.table-cell .table-cell-action i[data-v-2dc3e6c7]{font-size:14px;color:#fff;margin:0 5px;cursor:pointer}.table-cell .table-cell-handler[data-v-2dc3e6c7]{position:absolute;top:-2px;left:-2px;height:22px;line-height:22px;background:#409EFF;z-index:9}.table-cell .table-cell-handler i[data-v-2dc3e6c7]{font-size:14px;font-style:normal;color:#fff;margin:4px;cursor:default}.table-cell-action[data-v-2dc3e6c7] .svg-icon,.table-cell-handler[data-v-2dc3e6c7] .svg-icon{margin-left:.1em;margin-right:.1em}.table-cell.selected[data-v-2dc3e6c7]{outline:2px solid #409EFF!important}.primary-color[data-v-2fde56df]{color:#409eff}.background-opacity[data-v-2fde56df]{background:rgba(64,158,255,.6)}.form-widget-list .ghost[data-v-2fde56df]{content:"";font-size:0;height:3px;box-sizing:border-box;background:#409EFF;border:2px solid #409EFF;outline-width:0;padding:0;overflow:hidden}.el-form-item .el-rate[data-v-2fde56df]{margin-top:8px}.el-form-item--medium .el-radio[data-v-2fde56df]{line-height:36px!important}.el-form-item--medium .el-rate[data-v-2fde56df]{margin-top:8px}.el-form-item--small .el-radio[data-v-2fde56df]{line-height:32px!important}.el-form-item--small .el-rate[data-v-2fde56df]{margin-top:6px}.el-form-item--mini .el-radio[data-v-2fde56df]{line-height:28px!important}.el-form-item--mini .el-rate[data-v-2fde56df]{margin-top:4px}.el-card[data-v-2fde56df]{margin-top:3px;margin-bottom:3px}input[type=password][data-v-2fde56df]::-ms-reveal{display:none}.auto-full-width.el-date-editor.el-input[data-v-2fde56df],.auto-full-width.el-date-editor.el-input__inner[data-v-2fde56df]{width:100%!important}[data-v-2fde56df]::-webkit-scrollbar{width:8px;height:8px}[data-v-2fde56df]::-webkit-scrollbar-track{width:8px;background:rgba(16,31,28,.1);-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-2fde56df]::-webkit-scrollbar-thumb{background-color:#101f1c59;background-clip:padding-box;min-height:28px;-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-2fde56df]::-webkit-scrollbar-thumb:hover{background-color:#101f1cd9}*[data-v-2fde56df]{scrollbar-color:#e5e5e5 #f7f7f9;scrollbar-width:thin}div.table-container[data-v-2fde56df]{padding:5px;border:1px dashed #336699;box-sizing:border-box}div.table-container table.table-layout[data-v-2fde56df]{width:100%;text-align:center;border-collapse:collapse;table-layout:fixed}div.table-container table.table-layout[data-v-2fde56df] td{height:48px;border:1px dashed #336699;padding:3px;display:table-cell}div.table-container table.table-layout .form-widget-list[data-v-2fde56df]{border:1px dashed #336699;min-height:36px}.table-container.selected[data-v-2fde56df]{outline:2px solid #409EFF!important}.primary-color[data-v-32a29dc2]{color:#409eff}.background-opacity[data-v-32a29dc2]{background:rgba(64,158,255,.6)}.form-widget-list .ghost[data-v-32a29dc2]{content:"";font-size:0;height:3px;box-sizing:border-box;background:#409EFF;border:2px solid #409EFF;outline-width:0;padding:0;overflow:hidden}.el-form-item .el-rate[data-v-32a29dc2]{margin-top:8px}.el-form-item--medium .el-radio[data-v-32a29dc2]{line-height:36px!important}.el-form-item--medium .el-rate[data-v-32a29dc2]{margin-top:8px}.el-form-item--small .el-radio[data-v-32a29dc2]{line-height:32px!important}.el-form-item--small .el-rate[data-v-32a29dc2]{margin-top:6px}.el-form-item--mini .el-radio[data-v-32a29dc2]{line-height:28px!important}.el-form-item--mini .el-rate[data-v-32a29dc2]{margin-top:4px}.el-card[data-v-32a29dc2]{margin-top:3px;margin-bottom:3px}input[type=password][data-v-32a29dc2]::-ms-reveal{display:none}.auto-full-width.el-date-editor.el-input[data-v-32a29dc2],.auto-full-width.el-date-editor.el-input__inner[data-v-32a29dc2]{width:100%!important}[data-v-32a29dc2]::-webkit-scrollbar{width:8px;height:8px}[data-v-32a29dc2]::-webkit-scrollbar-track{width:8px;background:rgba(16,31,28,.1);-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-32a29dc2]::-webkit-scrollbar-thumb{background-color:#101f1c59;background-clip:padding-box;min-height:28px;-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-32a29dc2]::-webkit-scrollbar-thumb:hover{background-color:#101f1cd9}*[data-v-32a29dc2]{scrollbar-color:#e5e5e5 #f7f7f9;scrollbar-width:thin}.container-scroll-bar[data-v-32a29dc2] .el-scrollbar__wrap,.container-scroll-bar[data-v-32a29dc2] .el-scrollbar__view{overflow-x:hidden}.form-widget-container[data-v-32a29dc2]{padding:10px;background:#f1f2f3;overflow-x:hidden;overflow-y:auto}.form-widget-container .el-form.full-height-width[data-v-32a29dc2]{height:100%;padding:3px;background:#ffffff}.form-widget-container .el-form.full-height-width .no-widget-hint[data-v-32a29dc2]{position:absolute;left:0;right:0;top:0;bottom:0;height:100%;display:flex;align-items:center;justify-content:center;text-align:center;font-size:18px;color:#999}.form-widget-container .el-form.full-height-width .form-widget-list[data-v-32a29dc2]{min-height:calc(100vh - 124px);padding:3px}.form-widget-container .el-form.Pad-layout[data-v-32a29dc2]{margin:0 auto;max-width:960px;border-radius:15px;box-shadow:0 0 1px 10px #495060}.form-widget-container .el-form.H5-layout[data-v-32a29dc2]{margin:0 auto;width:420px;border-radius:15px;box-shadow:0 0 1px 10px #495060}.form-widget-container .el-form.widget-form[data-v-32a29dc2] .el-row{padding:2px;border:1px dashed rgba(170,170,170,.75)}.grid-cell[data-v-32a29dc2]{min-height:30px;border-right:1px dotted #cccccc}.fade-enter-active[data-v-32a29dc2],.fade-leave-active[data-v-32a29dc2]{transition:opacity .5s}.fade-enter[data-v-32a29dc2],.fade-leave-to[data-v-32a29dc2]{opacity:0}.primary-color[data-v-26b2429d]{color:#409eff}.background-opacity[data-v-26b2429d]{background:rgba(64,158,255,.6)}.form-widget-list .ghost[data-v-26b2429d]{content:"";font-size:0;height:3px;box-sizing:border-box;background:#409EFF;border:2px solid #409EFF;outline-width:0;padding:0;overflow:hidden}.el-form-item .el-rate[data-v-26b2429d]{margin-top:8px}.el-form-item--medium .el-radio[data-v-26b2429d]{line-height:36px!important}.el-form-item--medium .el-rate[data-v-26b2429d]{margin-top:8px}.el-form-item--small .el-radio[data-v-26b2429d]{line-height:32px!important}.el-form-item--small .el-rate[data-v-26b2429d]{margin-top:6px}.el-form-item--mini .el-radio[data-v-26b2429d]{line-height:28px!important}.el-form-item--mini .el-rate[data-v-26b2429d]{margin-top:4px}.el-card[data-v-26b2429d]{margin-top:3px;margin-bottom:3px}input[type=password][data-v-26b2429d]::-ms-reveal{display:none}.auto-full-width.el-date-editor.el-input[data-v-26b2429d],.auto-full-width.el-date-editor.el-input__inner[data-v-26b2429d]{width:100%!important}[data-v-26b2429d]::-webkit-scrollbar{width:8px;height:8px}[data-v-26b2429d]::-webkit-scrollbar-track{width:8px;background:rgba(16,31,28,.1);-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-26b2429d]::-webkit-scrollbar-thumb{background-color:#101f1c59;background-clip:padding-box;min-height:28px;-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-26b2429d]::-webkit-scrollbar-thumb:hover{background-color:#101f1cd9}*[data-v-26b2429d]{scrollbar-color:#e5e5e5 #f7f7f9;scrollbar-width:thin}.el-container.main-container[data-v-26b2429d]{background:#fff}.el-container.main-container[data-v-26b2429d] aside{margin:0;padding:0;background:inherit}.el-container.full-height[data-v-26b2429d]{height:100%;overflow-y:hidden}.el-container.center-layout-container[data-v-26b2429d]{min-width:680px;border-left:2px dotted #EBEEF5;border-right:2px dotted #EBEEF5}.el-header.main-header[data-v-26b2429d]{border-bottom:2px dotted #EBEEF5;height:48px!important;line-height:48px!important;min-width:800px}div.main-title[data-v-26b2429d]{font-size:18px;color:#242424;display:flex;align-items:center;justify-items:center}div.main-title img[data-v-26b2429d]{cursor:pointer;width:36px;height:36px}div.main-title span.bold[data-v-26b2429d]{font-size:20px;font-weight:700;margin:0 6px}div.main-title span.version-span[data-v-26b2429d]{font-size:14px;color:#101f1c;margin-left:6px}.float-left[data-v-26b2429d]{float:left}.float-right[data-v-26b2429d]{float:right}.el-dropdown-link[data-v-26b2429d]{margin-right:12px;cursor:pointer}div.external-link[data-v-26b2429d]{display:flex;align-items:center}div.external-link a[data-v-26b2429d]{font-size:13px;text-decoration:none;margin-right:10px;color:#606266}.el-header.toolbar-header[data-v-26b2429d]{font-size:14px;border-bottom:1px dotted #CCCCCC;height:42px!important}.el-aside.side-panel[data-v-26b2429d]{width:260px!important;overflow-y:hidden}.el-main.form-widget-main[data-v-26b2429d]{padding:0;position:relative;overflow-x:hidden}.container-scroll-bar[data-v-26b2429d] .el-scrollbar__wrap,.container-scroll-bar[data-v-26b2429d] .el-scrollbar__view{overflow-x:hidden}@font-face{font-family:iconfont;src:url(data:font/ttf;base64,AAEAAAALAIAAAwAwR1NVQiCLJXoAAAE4AAAAVE9TLzI8i0leAAABjAAAAFZjbWFw7bW54gAAAfgAAAGqZ2x5Zpkon+wAAAOwAAADNGhlYWQcnMJsAAAA4AAAADZoaGVhB4IDhgAAALwAAAAkaG10eBQAAAAAAAHkAAAAFGxvY2EBeAI2AAADpAAAAAxtYXhwARcAagAAARgAAAAgbmFtZT5U/n0AAAbkAAACbXBvc3T0IfeLAAAJVAAAAFAAAQAAA4D/gAAABAAAAAAABAAAAQAAAAAAAAAAAAAAAAAAAAUAAQAAAAEAALwRH5pfDzz1AAsEAAAAAADcvr83AAAAANy+vzcAAP+ABAADgQAAAAgAAgAAAAAAAAABAAAABQBeAAgAAAAAAAIAAAAKAAoAAAD/AAAAAAAAAAEAAAAKADAAPgACREZMVAAObGF0bgAaAAQAAAAAAAAAAQAAAAQAAAAAAAAAAQAAAAFsaWdhAAgAAAABAAAAAQAEAAQAAAABAAgAAQAGAAAAAQAAAAEEAAGQAAUAAAKJAswAAACPAokCzAAAAesAMgEIAAACAAUDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFBmRWQAQOYd52sDgP+AAFwDgQCAAAAAAQAAAAAAAAQAAAAEAAAABAAAAAQAAAAEAAAAAAAABQAAAAMAAAAsAAAABAAAAWoAAQAAAAAAZAADAAEAAAAsAAMACgAAAWoABAA4AAAACAAIAAIAAOYd51Tna///AADmHedT52v//wAAAAAAAAABAAgACAAKAAAABAABAAIAAwAAAQYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAAAQAAAAAAAAAAEAADmHQAA5h0AAAAEAADnUwAA51MAAAABAADnVAAA51QAAAACAADnawAA52sAAAADAAAAAAAAAE4AnAEqAZoABAAA/8AEAANAABoAHgAmAC4AACU2MhcWDwEUDwEGDwEiFAcjIiYvASY+ATIfAQMRIREBESMRIREjAyERIxEhESMDAo0KGwoFAQEJfQIJAgICAwQJBYwJBRQbCmmlAUD9wEABAD8BAkBAAQA/AbYKCgUMBg0KfwIEAQEBBASACRsUCmQC7v3AAkD9gP8AAUD+wAEA/wABQP7AAQAABAAA/4ADwANAABoAHgAmAC4AACUWFAcGLwEiLwEmLwE0Iic1NDY/ATYeARQPASUhESEBITUhESE1JREhNSERITUlATYKCgUMBg0KfwIEAQEBBASACRsUCmQC7v3AAkD9gP8AAUD+wAEA/wABQP7AAQDzChsKBQEBCX0CCQICAgMECQWMCQUUGwpppf7AAkBA/wA/Af3AQP8APwEABQAAAAADwgL9ACYAOQBBAEkAXQAAASYnNzY0JiIPASYjIgcGBwYUFxYXFhcHBhQXFjI/ARYzMjY3Njc2BTY3NjMyFwcuASMiDgEVFBcHJiUUBiMiJzcWBzQ2MzIXByYXIic3HgEzMj4BNTQnNxYXDgEHBgO9TWNpChMaCXRdeZF9XlEFBSIqMDRtCQkPGAl0YHZcs0RHIwX8xEZSanhcSlAQLRksSSsaWlIBkjcpFhSACsA3KRYUgApgXEpQEC0ZLEkrGlpUSSF6SkwBkINKaQoaEwpzQGRLgQcSBzkyOSltCRoJCgpzPU9FR1gPAm5AUi1QDg8rSSwxKVlBcik3CoAUFik3CoAU6i1QDg8rSSwxKVlAc0l1ICIAAAAIAAD/gANBA4EACAARABoAIwAsADUAPgBHAAABIiY0NjIWFAYDIiY0NjIWFAYDIiY0NjIWFAYDIiY0NjIWFAYBIiY0NjIWFAYDIiY0NjIWFAYDIiY0NjIWFAYDIiY0NjIWFAYBICg4OFA4OCgoODhQODgoKDg4UDg4KCg4OFA4OAGYKDg4UDg4KCg4OFA4OCgoODhQODgoKDg4UDg4AsA4UDg4UDj+6zhPOTlPOP7qOU84OE85/us4UDg4UDgDQDhQODhQOP7rOE85OU84/uo5Tzg4Tzn+6zhQODhQOAAAAAAAEgDeAAEAAAAAAAAAFQAAAAEAAAAAAAEACAAVAAEAAAAAAAIABwAdAAEAAAAAAAMACAAkAAEAAAAAAAQACAAsAAEAAAAAAAUACwA0AAEAAAAAAAYACAA/AAEAAAAAAAoAKwBHAAEAAAAAAAsAEwByAAMAAQQJAAAAKgCFAAMAAQQJAAEAEACvAAMAAQQJAAIADgC/AAMAAQQJAAMAEADNAAMAAQQJAAQAEADdAAMAAQQJAAUAFgDtAAMAAQQJAAYAEAEDAAMAAQQJAAoAVgETAAMAAQQJAAsAJgFpCkNyZWF0ZWQgYnkgaWNvbmZvbnQKaWNvbmZvbnRSZWd1bGFyaWNvbmZvbnRpY29uZm9udFZlcnNpb24gMS4waWNvbmZvbnRHZW5lcmF0ZWQgYnkgc3ZnMnR0ZiBmcm9tIEZvbnRlbGxvIHByb2plY3QuaHR0cDovL2ZvbnRlbGxvLmNvbQAKAEMAcgBlAGEAdABlAGQAIABiAHkAIABpAGMAbwBuAGYAbwBuAHQACgBpAGMAbwBuAGYAbwBuAHQAUgBlAGcAdQBsAGEAcgBpAGMAbwBuAGYAbwBuAHQAaQBjAG8AbgBmAG8AbgB0AFYAZQByAHMAaQBvAG4AIAAxAC4AMABpAGMAbwBuAGYAbwBuAHQARwBlAG4AZQByAGEAdABlAGQAIABiAHkAIABzAHYAZwAyAHQAdABmACAAZgByAG8AbQAgAEYAbwBuAHQAZQBsAGwAbwAgAHAAcgBvAGoAZQBjAHQALgBoAHQAdABwADoALwAvAGYAbwBuAHQAZQBsAGwAbwAuAGMAbwBtAAAAAAIAAAAAAAAACgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQECAQMBBAEFAQYADGluc2VydGNvbHVtbglpbnNlcnRyb3cEaGlkZQRkcmFnAAA=) format("truetype")}.iconfont{font-family:iconfont!important;font-size:16px;font-style:normal;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.icon-insertcolumn:before{content:"\e753"}.icon-insertrow:before{content:"\e754"}.icon-hide:before{content:"\e76b"}.icon-drag:before{content:"\e61d"}.primary-color[data-v-06588696]{color:#409eff}.background-opacity[data-v-06588696]{background:rgba(64,158,255,.6)}.form-widget-list .ghost[data-v-06588696]{content:"";font-size:0;height:3px;box-sizing:border-box;background:#409EFF;border:2px solid #409EFF;outline-width:0;padding:0;overflow:hidden}.el-form-item .el-rate[data-v-06588696]{margin-top:8px}.el-form-item--medium .el-radio[data-v-06588696]{line-height:36px!important}.el-form-item--medium .el-rate[data-v-06588696]{margin-top:8px}.el-form-item--small .el-radio[data-v-06588696]{line-height:32px!important}.el-form-item--small .el-rate[data-v-06588696]{margin-top:6px}.el-form-item--mini .el-radio[data-v-06588696]{line-height:28px!important}.el-form-item--mini .el-rate[data-v-06588696]{margin-top:4px}.el-card[data-v-06588696]{margin-top:3px;margin-bottom:3px}input[type=password][data-v-06588696]::-ms-reveal{display:none}.auto-full-width.el-date-editor.el-input[data-v-06588696],.auto-full-width.el-date-editor.el-input__inner[data-v-06588696]{width:100%!important}[data-v-06588696]::-webkit-scrollbar{width:8px;height:8px}[data-v-06588696]::-webkit-scrollbar-track{width:8px;background:rgba(16,31,28,.1);-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-06588696]::-webkit-scrollbar-thumb{background-color:#101f1c59;background-clip:padding-box;min-height:28px;-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-06588696]::-webkit-scrollbar-thumb:hover{background-color:#101f1cd9}*[data-v-06588696]{scrollbar-color:#e5e5e5 #f7f7f9;scrollbar-width:thin}.card-container.selected[data-v-06588696]{outline:2px solid #409EFF!important}.card-container[data-v-06588696]{margin:3px}.card-container .form-widget-list[data-v-06588696]{min-height:28px}[data-v-06588696] .el-card__header{padding:10px 12px}.folded[data-v-06588696] .el-card__body{display:none}.clear-fix[data-v-06588696]:before,.clear-fix[data-v-06588696]:after{display:table;content:""}.clear-fix[data-v-06588696]:after{clear:both}.float-right[data-v-06588696]{float:right}.primary-color[data-v-52275f84]{color:#409eff}.background-opacity[data-v-52275f84]{background:rgba(64,158,255,.6)}.form-widget-list .ghost[data-v-52275f84]{content:"";font-size:0;height:3px;box-sizing:border-box;background:#409EFF;border:2px solid #409EFF;outline-width:0;padding:0;overflow:hidden}.el-form-item .el-rate[data-v-52275f84]{margin-top:8px}.el-form-item--medium .el-radio[data-v-52275f84]{line-height:36px!important}.el-form-item--medium .el-rate[data-v-52275f84]{margin-top:8px}.el-form-item--small .el-radio[data-v-52275f84]{line-height:32px!important}.el-form-item--small .el-rate[data-v-52275f84]{margin-top:6px}.el-form-item--mini .el-radio[data-v-52275f84]{line-height:28px!important}.el-form-item--mini .el-rate[data-v-52275f84]{margin-top:4px}.el-card[data-v-52275f84]{margin-top:3px;margin-bottom:3px}input[type=password][data-v-52275f84]::-ms-reveal{display:none}.auto-full-width.el-date-editor.el-input[data-v-52275f84],.auto-full-width.el-date-editor.el-input__inner[data-v-52275f84]{width:100%!important}[data-v-52275f84]::-webkit-scrollbar{width:8px;height:8px}[data-v-52275f84]::-webkit-scrollbar-track{width:8px;background:rgba(16,31,28,.1);-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-52275f84]::-webkit-scrollbar-thumb{background-color:#101f1c59;background-clip:padding-box;min-height:28px;-webkit-border-radius:2em;-moz-border-radius:2em;border-radius:2em}[data-v-52275f84]::-webkit-scrollbar-thumb:hover{background-color:#101f1cd9}*[data-v-52275f84]{scrollbar-color:#e5e5e5 #f7f7f9;scrollbar-width:thin}[data-v-52275f84] .el-card__header{padding:10px 12px}.folded[data-v-52275f84] .el-card__body{display:none}.clear-fix[data-v-52275f84]:before,.clear-fix[data-v-52275f84]:after{display:table;content:""}.clear-fix[data-v-52275f84]:after{clear:both}.float-right[data-v-52275f84]{float:right} diff --git a/lib/vform/designer.umd.js b/lib/vform/designer.umd.js new file mode 100644 index 0000000..20e271a --- /dev/null +++ b/lib/vform/designer.umd.js @@ -0,0 +1,1649 @@ +var Ae=Object.defineProperty,Re=Object.defineProperties;var Fe=Object.getOwnPropertyDescriptors;var Me=Object.getOwnPropertySymbols;var Ne=Object.prototype.hasOwnProperty,Ie=Object.prototype.propertyIsEnumerable;var Le=(t,d,e)=>d in t?Ae(t,d,{enumerable:!0,configurable:!0,writable:!0,value:e}):t[d]=e,Se=(t,d)=>{for(var e in d||(d={}))Ne.call(d,e)&&Le(t,e,d[e]);if(Me)for(var e of Me(d))Ie.call(d,e)&&Le(t,e,d[e]);return t},ke=(t,d)=>Re(t,Fe(d));(function(t,d){typeof exports=="object"&&typeof module!="undefined"?module.exports=d(require("vue")):typeof define=="function"&&define.amd?define(["vue"],d):(t=typeof globalThis!="undefined"?globalThis:t||self,t.VFormDesigner=d(t.Vue))})(this,function(require$$0$1){"use strict";function _interopDefaultLegacy(t){return t&&typeof t=="object"&&"default"in t?t:{default:t}}var require$$0__default=_interopDefaultLegacy(require$$0$1),commonjsGlobal=typeof globalThis!="undefined"?globalThis:typeof window!="undefined"?window:typeof global!="undefined"?global:typeof self!="undefined"?self:{};function getDefaultExportFromCjs(t){return t&&t.__esModule&&Object.prototype.hasOwnProperty.call(t,"default")?t.default:t}var axios$2={exports:{}},bind$2=function(d,e){return function(){for(var m=new Array(arguments.length),g=0;g=0)return;h==="set-cookie"?e[h]=(e[h]?e[h]:[]).concat([m]):e[h]=e[h]?e[h]+", "+m:m}}),e},utils$7=utils$d,isURLSameOrigin$1=utils$7.isStandardBrowserEnv()?function(){var d=/(msie|trident)/i.test(navigator.userAgent),e=document.createElement("a"),h;function m(g){var a=g;return d&&(e.setAttribute("href",a),a=e.href),e.setAttribute("href",a),{href:e.href,protocol:e.protocol?e.protocol.replace(/:$/,""):"",host:e.host,search:e.search?e.search.replace(/^\?/,""):"",hash:e.hash?e.hash.replace(/^#/,""):"",hostname:e.hostname,port:e.port,pathname:e.pathname.charAt(0)==="/"?e.pathname:"/"+e.pathname}}return h=m(window.location.href),function(a){var u=utils$7.isString(a)?m(a):a;return u.protocol===h.protocol&&u.host===h.host}}():function(){return function(){return!0}}();function Cancel$3(t){this.message=t}Cancel$3.prototype.toString=function(){return"Cancel"+(this.message?": "+this.message:"")},Cancel$3.prototype.__CANCEL__=!0;var Cancel_1=Cancel$3,utils$6=utils$d,settle=settle$1,cookies=cookies$1,buildURL$1=buildURL$2,buildFullPath=buildFullPath$1,parseHeaders=parseHeaders$1,isURLSameOrigin=isURLSameOrigin$1,createError=createError$2,defaults$5=defaults_1,Cancel$2=Cancel_1,xhr=function(d){return new Promise(function(h,m){var g=d.data,a=d.headers,u=d.responseType,r;function f(){d.cancelToken&&d.cancelToken.unsubscribe(r),d.signal&&d.signal.removeEventListener("abort",r)}utils$6.isFormData(g)&&delete a["Content-Type"];var l=new XMLHttpRequest;if(d.auth){var n=d.auth.username||"",i=d.auth.password?unescape(encodeURIComponent(d.auth.password)):"";a.Authorization="Basic "+btoa(n+":"+i)}var o=buildFullPath(d.baseURL,d.url);l.open(d.method.toUpperCase(),buildURL$1(o,d.params,d.paramsSerializer),!0),l.timeout=d.timeout;function s(){if(!!l){var p="getAllResponseHeaders"in l?parseHeaders(l.getAllResponseHeaders()):null,$=!u||u==="text"||u==="json"?l.responseText:l.response,v={data:$,status:l.status,statusText:l.statusText,headers:p,config:d,request:l};settle(function(y){h(y),f()},function(y){m(y),f()},v),l=null}}if("onloadend"in l?l.onloadend=s:l.onreadystatechange=function(){!l||l.readyState!==4||l.status===0&&!(l.responseURL&&l.responseURL.indexOf("file:")===0)||setTimeout(s)},l.onabort=function(){!l||(m(createError("Request aborted",d,"ECONNABORTED",l)),l=null)},l.onerror=function(){m(createError("Network Error",d,null,l)),l=null},l.ontimeout=function(){var $=d.timeout?"timeout of "+d.timeout+"ms exceeded":"timeout exceeded",v=d.transitional||defaults$5.transitional;d.timeoutErrorMessage&&($=d.timeoutErrorMessage),m(createError($,d,v.clarifyTimeoutError?"ETIMEDOUT":"ECONNABORTED",l)),l=null},utils$6.isStandardBrowserEnv()){var c=(d.withCredentials||isURLSameOrigin(o))&&d.xsrfCookieName?cookies.read(d.xsrfCookieName):void 0;c&&(a[d.xsrfHeaderName]=c)}"setRequestHeader"in l&&utils$6.forEach(a,function($,v){typeof g=="undefined"&&v.toLowerCase()==="content-type"?delete a[v]:l.setRequestHeader(v,$)}),utils$6.isUndefined(d.withCredentials)||(l.withCredentials=!!d.withCredentials),u&&u!=="json"&&(l.responseType=d.responseType),typeof d.onDownloadProgress=="function"&&l.addEventListener("progress",d.onDownloadProgress),typeof d.onUploadProgress=="function"&&l.upload&&l.upload.addEventListener("progress",d.onUploadProgress),(d.cancelToken||d.signal)&&(r=function(p){!l||(m(!p||p&&p.type?new Cancel$2("canceled"):p),l.abort(),l=null)},d.cancelToken&&d.cancelToken.subscribe(r),d.signal&&(d.signal.aborted?r():d.signal.addEventListener("abort",r))),g||(g=null),l.send(g)})},utils$5=utils$d,normalizeHeaderName=normalizeHeaderName$1,enhanceError=enhanceError$2,DEFAULT_CONTENT_TYPE={"Content-Type":"application/x-www-form-urlencoded"};function setContentTypeIfUnset(t,d){!utils$5.isUndefined(t)&&utils$5.isUndefined(t["Content-Type"])&&(t["Content-Type"]=d)}function getDefaultAdapter(){var t;return(typeof XMLHttpRequest!="undefined"||typeof process!="undefined"&&Object.prototype.toString.call(process)==="[object process]")&&(t=xhr),t}function stringifySafely(t,d,e){if(utils$5.isString(t))try{return(d||JSON.parse)(t),utils$5.trim(t)}catch(h){if(h.name!=="SyntaxError")throw h}return(e||JSON.stringify)(t)}var defaults$4={transitional:{silentJSONParsing:!0,forcedJSONParsing:!0,clarifyTimeoutError:!1},adapter:getDefaultAdapter(),transformRequest:[function(d,e){return normalizeHeaderName(e,"Accept"),normalizeHeaderName(e,"Content-Type"),utils$5.isFormData(d)||utils$5.isArrayBuffer(d)||utils$5.isBuffer(d)||utils$5.isStream(d)||utils$5.isFile(d)||utils$5.isBlob(d)?d:utils$5.isArrayBufferView(d)?d.buffer:utils$5.isURLSearchParams(d)?(setContentTypeIfUnset(e,"application/x-www-form-urlencoded;charset=utf-8"),d.toString()):utils$5.isObject(d)||e&&e["Content-Type"]==="application/json"?(setContentTypeIfUnset(e,"application/json"),stringifySafely(d)):d}],transformResponse:[function(d){var e=this.transitional||defaults$4.transitional,h=e&&e.silentJSONParsing,m=e&&e.forcedJSONParsing,g=!h&&this.responseType==="json";if(g||m&&utils$5.isString(d)&&d.length)try{return JSON.parse(d)}catch(a){if(g)throw a.name==="SyntaxError"?enhanceError(a,this,"E_JSON_PARSE"):a}return d}],timeout:0,xsrfCookieName:"XSRF-TOKEN",xsrfHeaderName:"X-XSRF-TOKEN",maxContentLength:-1,maxBodyLength:-1,validateStatus:function(d){return d>=200&&d<300},headers:{common:{Accept:"application/json, text/plain, */*"}}};utils$5.forEach(["delete","get","head"],function(d){defaults$4.headers[d]={}}),utils$5.forEach(["post","put","patch"],function(d){defaults$4.headers[d]=utils$5.merge(DEFAULT_CONTENT_TYPE)});var defaults_1=defaults$4,utils$4=utils$d,defaults$3=defaults_1,transformData$1=function(d,e,h){var m=this||defaults$3;return utils$4.forEach(h,function(a){d=a.call(m,d,e)}),d},isCancel$1=function(d){return!!(d&&d.__CANCEL__)},utils$3=utils$d,transformData=transformData$1,isCancel=isCancel$1,defaults$2=defaults_1,Cancel$1=Cancel_1;function throwIfCancellationRequested(t){if(t.cancelToken&&t.cancelToken.throwIfRequested(),t.signal&&t.signal.aborted)throw new Cancel$1("canceled")}var dispatchRequest$1=function(d){throwIfCancellationRequested(d),d.headers=d.headers||{},d.data=transformData.call(d,d.data,d.headers,d.transformRequest),d.headers=utils$3.merge(d.headers.common||{},d.headers[d.method]||{},d.headers),utils$3.forEach(["delete","get","head","post","put","patch","common"],function(m){delete d.headers[m]});var e=d.adapter||defaults$2.adapter;return e(d).then(function(m){return throwIfCancellationRequested(d),m.data=transformData.call(d,m.data,m.headers,d.transformResponse),m},function(m){return isCancel(m)||(throwIfCancellationRequested(d),m&&m.response&&(m.response.data=transformData.call(d,m.response.data,m.response.headers,d.transformResponse))),Promise.reject(m)})},utils$2=utils$d,mergeConfig$2=function(d,e){e=e||{};var h={};function m(l,n){return utils$2.isPlainObject(l)&&utils$2.isPlainObject(n)?utils$2.merge(l,n):utils$2.isPlainObject(n)?utils$2.merge({},n):utils$2.isArray(n)?n.slice():n}function g(l){if(utils$2.isUndefined(e[l])){if(!utils$2.isUndefined(d[l]))return m(void 0,d[l])}else return m(d[l],e[l])}function a(l){if(!utils$2.isUndefined(e[l]))return m(void 0,e[l])}function u(l){if(utils$2.isUndefined(e[l])){if(!utils$2.isUndefined(d[l]))return m(void 0,d[l])}else return m(void 0,e[l])}function r(l){if(l in e)return m(d[l],e[l]);if(l in d)return m(void 0,d[l])}var f={url:a,method:a,data:a,baseURL:u,transformRequest:u,transformResponse:u,paramsSerializer:u,timeout:u,timeoutMessage:u,withCredentials:u,adapter:u,responseType:u,xsrfCookieName:u,xsrfHeaderName:u,onUploadProgress:u,onDownloadProgress:u,decompress:u,maxContentLength:u,maxBodyLength:u,transport:u,httpAgent:u,httpsAgent:u,cancelToken:u,socketPath:u,responseEncoding:u,validateStatus:r};return utils$2.forEach(Object.keys(d).concat(Object.keys(e)),function(n){var i=f[n]||g,o=i(n);utils$2.isUndefined(o)&&i!==r||(h[n]=o)}),h},data={version:"0.24.0"},VERSION=data.version,validators$1={};["object","boolean","number","function","string","symbol"].forEach(function(t,d){validators$1[t]=function(h){return typeof h===t||"a"+(d<1?"n ":" ")+t}});var deprecatedWarnings={};validators$1.transitional=function(d,e,h){function m(g,a){return"[Axios v"+VERSION+"] Transitional option '"+g+"'"+a+(h?". "+h:"")}return function(g,a,u){if(d===!1)throw new Error(m(a," has been removed"+(e?" in "+e:"")));return e&&!deprecatedWarnings[a]&&(deprecatedWarnings[a]=!0,console.warn(m(a," has been deprecated since v"+e+" and will be removed in the near future"))),d?d(g,a,u):!0}};function assertOptions(t,d,e){if(typeof t!="object")throw new TypeError("options must be an object");for(var h=Object.keys(t),m=h.length;m-- >0;){var g=h[m],a=d[g];if(a){var u=t[g],r=u===void 0||a(u,g,t);if(r!==!0)throw new TypeError("option "+g+" must be "+r);continue}if(e!==!0)throw Error("Unknown option "+g)}}var validator$1={assertOptions,validators:validators$1},utils$1=utils$d,buildURL=buildURL$2,InterceptorManager=InterceptorManager_1,dispatchRequest=dispatchRequest$1,mergeConfig$1=mergeConfig$2,validator=validator$1,validators=validator.validators;function Axios$1(t){this.defaults=t,this.interceptors={request:new InterceptorManager,response:new InterceptorManager}}Axios$1.prototype.request=function(d){typeof d=="string"?(d=arguments[1]||{},d.url=arguments[0]):d=d||{},d=mergeConfig$1(this.defaults,d),d.method?d.method=d.method.toLowerCase():this.defaults.method?d.method=this.defaults.method.toLowerCase():d.method="get";var e=d.transitional;e!==void 0&&validator.assertOptions(e,{silentJSONParsing:validators.transitional(validators.boolean),forcedJSONParsing:validators.transitional(validators.boolean),clarifyTimeoutError:validators.transitional(validators.boolean)},!1);var h=[],m=!0;this.interceptors.request.forEach(function(i){typeof i.runWhen=="function"&&i.runWhen(d)===!1||(m=m&&i.synchronous,h.unshift(i.fulfilled,i.rejected))});var g=[];this.interceptors.response.forEach(function(i){g.push(i.fulfilled,i.rejected)});var a;if(!m){var u=[dispatchRequest,void 0];for(Array.prototype.unshift.apply(u,h),u=u.concat(g),a=Promise.resolve(d);u.length;)a=a.then(u.shift(),u.shift());return a}for(var r=d;h.length;){var f=h.shift(),l=h.shift();try{r=f(r)}catch(n){l(n);break}}try{a=dispatchRequest(r)}catch(n){return Promise.reject(n)}for(;g.length;)a=a.then(g.shift(),g.shift());return a},Axios$1.prototype.getUri=function(d){return d=mergeConfig$1(this.defaults,d),buildURL(d.url,d.params,d.paramsSerializer).replace(/^\?/,"")},utils$1.forEach(["delete","get","head","options"],function(d){Axios$1.prototype[d]=function(e,h){return this.request(mergeConfig$1(h||{},{method:d,url:e,data:(h||{}).data}))}}),utils$1.forEach(["post","put","patch"],function(d){Axios$1.prototype[d]=function(e,h,m){return this.request(mergeConfig$1(m||{},{method:d,url:e,data:h}))}});var Axios_1=Axios$1,Cancel=Cancel_1;function CancelToken(t){if(typeof t!="function")throw new TypeError("executor must be a function.");var d;this.promise=new Promise(function(m){d=m});var e=this;this.promise.then(function(h){if(!!e._listeners){var m,g=e._listeners.length;for(m=0;mhtml text",customClass:"",onCreated:"",onMounted:""}},{type:"button",icon:"button",formItemFlag:!1,options:{name:"",label:"",columnWidth:"200px",size:"",displayStyle:"block",disabled:!1,hidden:!1,type:"",plain:!1,round:!1,circle:!1,icon:null,customClass:"",onCreated:"",onMounted:"",onClick:""}},{type:"divider",icon:"divider",formItemFlag:!1,options:{name:"",label:"",columnWidth:"200px",direction:"horizontal",contentPosition:"center",hidden:!1,customClass:"",onCreated:"",onMounted:""}}],advancedFields=[{type:"picture-upload",icon:"picture-upload-field",formItemFlag:!0,options:{name:"",label:"",labelAlign:"",labelWidth:null,labelHidden:!1,columnWidth:"200px",disabled:!1,hidden:!1,required:!1,requiredHint:"",customRule:"",customRuleHint:"",uploadURL:"",uploadTip:"",withCredentials:!1,multipleSelect:!1,showFileList:!0,limit:3,fileMaxSize:5,fileTypes:["jpg","jpeg","png"],customClass:"",labelIconClass:null,labelIconPosition:"rear",labelTooltip:null,onCreated:"",onMounted:"",onBeforeUpload:"",onUploadSuccess:"",onUploadError:"",onFileRemove:"",onValidate:""}},{type:"file-upload",icon:"file-upload-field",formItemFlag:!0,options:{name:"",label:"",labelAlign:"",labelWidth:null,labelHidden:!1,columnWidth:"200px",disabled:!1,hidden:!1,required:!1,requiredHint:"",customRule:"",customRuleHint:"",uploadURL:"",uploadTip:"",withCredentials:!1,multipleSelect:!1,showFileList:!0,limit:3,fileMaxSize:5,fileTypes:["doc","docx","xls","xlsx"],customClass:"",labelIconClass:null,labelIconPosition:"rear",labelTooltip:null,onCreated:"",onMounted:"",onBeforeUpload:"",onUploadSuccess:"",onUploadError:"",onFileRemove:"",onValidate:""}},{type:"rich-editor",icon:"rich-editor-field",formItemFlag:!0,options:{name:"",label:"",labelAlign:"",placeholder:"",labelWidth:null,labelHidden:!1,columnWidth:"200px",contentHeight:"200px",disabled:!1,hidden:!1,required:!1,requiredHint:"",customRule:"",customRuleHint:"",customClass:"",labelIconClass:null,labelIconPosition:"rear",labelTooltip:null,minLength:null,maxLength:null,showWordLimit:!1,onCreated:"",onMounted:"",onValidate:""}},{type:"cascader",icon:"cascader-field",formItemFlag:!0,options:{name:"",label:"",labelAlign:"",defaultValue:"",placeholder:"",size:"",labelWidth:null,labelHidden:!1,columnWidth:"200px",disabled:!1,hidden:!1,clearable:!0,filterable:!1,multiple:!1,checkStrictly:!1,showAllLevels:!0,optionItems:[{label:"select 1",value:1,children:[{label:"child 1",value:11}]},{label:"select 2",value:2},{label:"select 3",value:3}],required:!1,requiredHint:"",customRule:"",customRuleHint:"",customClass:"",labelIconClass:null,labelIconPosition:"rear",labelTooltip:null,onCreated:"",onMounted:"",onChange:"",onFocus:"",onBlur:"",onValidate:""}}],customFields=[];function addContainerWidgetSchema(t){containers.push(t)}function addCustomWidgetSchema(t){customFields.push(t)}const formTemplates=[{title:"\u5355\u5217\u8868\u5355",imgUrl:"https://ks3-cn-beijing.ksyuncs.com/vform-static/form-samples/t1.png",jsonUrl:"https://ks3-cn-beijing.ksyuncs.com/vform-static/form-samples/json1.txt",description:"\u8868\u5355\u6A21\u677F\u8BE6\u7EC6\u8BF4\u660E..."},{title:"\u591A\u5217\u8868\u5355",imgUrl:"https://ks3-cn-beijing.ksyuncs.com/vform-static/form-samples/t2.png",jsonUrl:"https://ks3-cn-beijing.ksyuncs.com/vform-static/form-samples/json2.txt",description:"\u8868\u5355\u6A21\u677F\u8BE6\u7EC6\u8BF4\u660E..."},{title:"\u5206\u7EC4\u8868\u5355",imgUrl:"https://ks3-cn-beijing.ksyuncs.com/vform-static/form-samples/t3.png",jsonUrl:"https://ks3-cn-beijing.ksyuncs.com/vform-static/form-samples/json3.txt",description:"\u8868\u5355\u6A21\u677F\u8BE6\u7EC6\u8BF4\u660E..."},{title:"\u6807\u7B7E\u9875\u8868\u5355",imgUrl:"https://ks3-cn-beijing.ksyuncs.com/vform-static/form-samples/t4.png",jsonUrl:"https://ks3-cn-beijing.ksyuncs.com/vform-static/form-samples/json4.txt",description:"\u8868\u5355\u6A21\u677F\u8BE6\u7EC6\u8BF4\u660E..."},{title:"\u4E3B\u4ECE\u8868\u5355",imgUrl:"https://ks3-cn-beijing.ksyuncs.com/vform-static/form-samples/t5.png",jsonUrl:"https://ks3-cn-beijing.ksyuncs.com/vform-static/form-samples/json5.txt",description:"\u8868\u5355\u6A21\u677F\u8BE6\u7EC6\u8BF4\u660E..."},{title:"\u54CD\u5E94\u5F0F\u8868\u5355",imgUrl:"https://ks3-cn-beijing.ksyuncs.com/vform-static/form-samples/t6.png",jsonUrl:"https://ks3-cn-beijing.ksyuncs.com/vform-static/form-samples/json6.txt",description:"\u8868\u5355\u6A21\u677F\u8BE6\u7EC6\u8BF4\u660E..."},{title:"\u95EE\u5377\u8C03\u67E5\u8868",imgUrl:"https://ks3-cn-beijing.ksyuncs.com/vform-static/form-samples/t7.png",jsonUrl:"https://ks3-cn-beijing.ksyuncs.com/vform-static/form-samples/json7.txt",description:"\u8868\u5355\u6A21\u677F\u8BE6\u7EC6\u8BF4\u660E..."},{title:"\u56FA\u5B9A\u8868\u683C\u8868\u5355",imgUrl:"https://ks3-cn-beijing.ksyuncs.com/vform-static/form-samples/t8.png",jsonUrl:"https://ks3-cn-beijing.ksyuncs.com/vform-static/form-samples/json8.txt",description:"\u8868\u5355\u6A21\u677F\u8BE6\u7EC6\u8BF4\u660E..."}];var clipboard={exports:{}};/*! + * clipboard.js v2.0.11 + * https://clipboardjs.com/ + * + * Licensed MIT © Zeno Rocha + */(function(t,d){(function(h,m){t.exports=m()})(commonjsGlobal,function(){return function(){var e={686:function(g,a,u){u.d(a,{default:function(){return R}});var r=u(279),f=u.n(r),l=u(370),n=u.n(l),i=u(817),o=u.n(i);function s(B){try{return document.execCommand(B)}catch{return!1}}var c=function(N){var P=o()(N);return s("cut"),P},p=c;function $(B){var N=document.documentElement.getAttribute("dir")==="rtl",P=document.createElement("textarea");P.style.fontSize="12pt",P.style.border="0",P.style.padding="0",P.style.margin="0",P.style.position="absolute",P.style[N?"right":"left"]="-9999px";var j=window.pageYOffset||document.documentElement.scrollTop;return P.style.top="".concat(j,"px"),P.setAttribute("readonly",""),P.value=B,P}var v=function(N,P){var j=$(N);P.container.appendChild(j);var D=o()(j);return s("copy"),j.remove(),D},C=function(N){var P=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{container:document.body},j="";return typeof N=="string"?j=v(N,P):N instanceof HTMLInputElement&&!["text","search","url","tel","password"].includes(N==null?void 0:N.type)?j=v(N.value,P):(j=o()(N),s("copy")),j},y=C;function _(B){return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?_=function(P){return typeof P}:_=function(P){return P&&typeof Symbol=="function"&&P.constructor===Symbol&&P!==Symbol.prototype?"symbol":typeof P},_(B)}var b=function(){var N=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{},P=N.action,j=P===void 0?"copy":P,D=N.container,W=N.target,H=N.text;if(j!=="copy"&&j!=="cut")throw new Error('Invalid "action" value, use either "copy" or "cut"');if(W!==void 0)if(W&&_(W)==="object"&&W.nodeType===1){if(j==="copy"&&W.hasAttribute("disabled"))throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute');if(j==="cut"&&(W.hasAttribute("readonly")||W.hasAttribute("disabled")))throw new Error(`Invalid "target" attribute. You can't cut text from elements with "readonly" or "disabled" attributes`)}else throw new Error('Invalid "target" value, use a valid Element');if(H)return y(H,{container:D});if(W)return j==="cut"?p(W):y(W,{container:D})},E=b;function x(B){return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?x=function(P){return typeof P}:x=function(P){return P&&typeof Symbol=="function"&&P.constructor===Symbol&&P!==Symbol.prototype?"symbol":typeof P},x(B)}function O(B,N){if(!(B instanceof N))throw new TypeError("Cannot call a class as a function")}function M(B,N){for(var P=0;P0&&arguments[0]!==void 0?arguments[0]:{};this.action=typeof D.action=="function"?D.action:this.defaultAction,this.target=typeof D.target=="function"?D.target:this.defaultTarget,this.text=typeof D.text=="function"?D.text:this.defaultText,this.container=x(D.container)==="object"?D.container:document.body}},{key:"listenClick",value:function(D){var W=this;this.listener=n()(D,"click",function(H){return W.onClick(H)})}},{key:"onClick",value:function(D){var W=D.delegateTarget||D.currentTarget,H=this.action(W)||"copy",z=E({action:H,container:this.container,target:this.target(W),text:this.text(W)});this.emit(z?"success":"error",{action:H,text:z,trigger:W,clearSelection:function(){W&&W.focus(),window.getSelection().removeAllRanges()}})}},{key:"defaultAction",value:function(D){return F("action",D)}},{key:"defaultTarget",value:function(D){var W=F("target",D);if(W)return document.querySelector(W)}},{key:"defaultText",value:function(D){return F("text",D)}},{key:"destroy",value:function(){this.listener.destroy()}}],[{key:"copy",value:function(D){var W=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{container:document.body};return y(D,W)}},{key:"cut",value:function(D){return p(D)}},{key:"isSupported",value:function(){var D=arguments.length>0&&arguments[0]!==void 0?arguments[0]:["copy","cut"],W=typeof D=="string"?[D]:D,H=!!document.queryCommandSupported;return W.forEach(function(z){H=H&&!!document.queryCommandSupported(z)}),H}}]),P}(f()),R=V},828:function(g){var a=9;if(typeof Element!="undefined"&&!Element.prototype.matches){var u=Element.prototype;u.matches=u.matchesSelector||u.mozMatchesSelector||u.msMatchesSelector||u.oMatchesSelector||u.webkitMatchesSelector}function r(f,l){for(;f&&f.nodeType!==a;){if(typeof f.matches=="function"&&f.matches(l))return f;f=f.parentNode}}g.exports=r},438:function(g,a,u){var r=u(828);function f(i,o,s,c,p){var $=n.apply(this,arguments);return i.addEventListener(s,$,p),{destroy:function(){i.removeEventListener(s,$,p)}}}function l(i,o,s,c,p){return typeof i.addEventListener=="function"?f.apply(null,arguments):typeof s=="function"?f.bind(null,document).apply(null,arguments):(typeof i=="string"&&(i=document.querySelectorAll(i)),Array.prototype.map.call(i,function($){return f($,o,s,c,p)}))}function n(i,o,s,c){return function(p){p.delegateTarget=r(p.target,o),p.delegateTarget&&c.call(i,p)}}g.exports=l},879:function(g,a){a.node=function(u){return u!==void 0&&u instanceof HTMLElement&&u.nodeType===1},a.nodeList=function(u){var r=Object.prototype.toString.call(u);return u!==void 0&&(r==="[object NodeList]"||r==="[object HTMLCollection]")&&"length"in u&&(u.length===0||a.node(u[0]))},a.string=function(u){return typeof u=="string"||u instanceof String},a.fn=function(u){var r=Object.prototype.toString.call(u);return r==="[object Function]"}},370:function(g,a,u){var r=u(879),f=u(438);function l(s,c,p){if(!s&&!c&&!p)throw new Error("Missing required arguments");if(!r.string(c))throw new TypeError("Second argument must be a String");if(!r.fn(p))throw new TypeError("Third argument must be a Function");if(r.node(s))return n(s,c,p);if(r.nodeList(s))return i(s,c,p);if(r.string(s))return o(s,c,p);throw new TypeError("First argument must be a String, HTMLElement, HTMLCollection, or NodeList")}function n(s,c,p){return s.addEventListener(c,p),{destroy:function(){s.removeEventListener(c,p)}}}function i(s,c,p){return Array.prototype.forEach.call(s,function($){$.addEventListener(c,p)}),{destroy:function(){Array.prototype.forEach.call(s,function($){$.removeEventListener(c,p)})}}}function o(s,c,p){return f(document.body,s,c,p)}g.exports=l},817:function(g){function a(u){var r;if(u.nodeName==="SELECT")u.focus(),r=u.value;else if(u.nodeName==="INPUT"||u.nodeName==="TEXTAREA"){var f=u.hasAttribute("readonly");f||u.setAttribute("readonly",""),u.select(),u.setSelectionRange(0,u.value.length),f||u.removeAttribute("readonly"),r=u.value}else{u.hasAttribute("contenteditable")&&u.focus();var l=window.getSelection(),n=document.createRange();n.selectNodeContents(u),l.removeAllRanges(),l.addRange(n),r=l.toString()}return r}g.exports=a},279:function(g){function a(){}a.prototype={on:function(u,r,f){var l=this.e||(this.e={});return(l[u]||(l[u]=[])).push({fn:r,ctx:f}),this},once:function(u,r,f){var l=this;function n(){l.off(u,n),r.apply(f,arguments)}return n._=r,this.on(u,n,f)},emit:function(u){var r=[].slice.call(arguments,1),f=((this.e||(this.e={}))[u]||[]).slice(),l=0,n=f.length;for(l;l{t[e]=d[e]})},evalFn=function(t,d=null,e=null){return new Function("DSV","VFR","return "+t)(d,e)},addWindowResizeHandler=function(t){let d=window.onresize;typeof window.onresize!="function"?window.onresize=t:window.onresize=function(){d(),t()}},insertCustomCssToHead=function(t,d=""){let e=document.getElementsByTagName("head")[0],h=document.getElementById("vform-custom-css");h&&e.removeChild(h),d&&(h=document.getElementById("vform-custom-css-"+d),!!h&&e.removeChild(h));let m=document.createElement("style");m.type="text/css",m.rel="stylesheet",m.id=d?"vform-custom-css-"+d:"vform-custom-css";try{m.appendChild(document.createTextNode(t))}catch{m.styleSheet.cssText=t}e.appendChild(m)},insertGlobalFunctionsToHtml=function(t,d=""){let e=document.getElementsByTagName("body")[0],h=document.getElementById("v_form_global_functions");!!h&&e.removeChild(h),d&&(h=document.getElementById("v_form_global_functions-"+d),!!h&&e.removeChild(h));let m=document.createElement("script");m.id=d?"v_form_global_functions-"+d:"v_form_global_functions",m.type="text/javascript",m.innerHTML=t,e.appendChild(m)},loadRemoteScript=function(t,d){let e=encodeURIComponent(t);if(!document.getElementById(e)){let m=document.createElement("script");m.src=t,m.id=e,document.body.appendChild(m),m.onload=m.onreadystatechange=function(g,a){(a||!m.readyState||m.readyState==="loaded"||m.readyState==="complete")&&(m=m.onload=m.onreadystatechange=null,a||d())}}};function traverseFieldWidgets(t,d,e=null){!t||t.map(h=>{h.formItemFlag?d(h,e):h.type==="grid"?h.cols.map(m=>{traverseFieldWidgets(m.widgetList,d,h)}):h.type==="table"?h.rows.map(m=>{m.cols.map(g=>{traverseFieldWidgets(g.widgetList,d,h)})}):h.type==="tab"?h.tabs.map(m=>{traverseFieldWidgets(m.widgetList,d,h)}):(h.type==="sub-form"||h.category==="container")&&traverseFieldWidgets(h.widgetList,d,h)})}function traverseContainerWidgets(t,d){!t||t.map(e=>{e.category==="container"&&d(e),e.type==="grid"?e.cols.map(h=>{traverseContainerWidgets(h.widgetList,d)}):e.type==="table"?e.rows.map(h=>{h.cols.map(m=>{traverseContainerWidgets(m.widgetList,d)})}):e.type==="tab"?e.tabs.map(h=>{traverseContainerWidgets(h.widgetList,d)}):(e.type==="sub-form"||e.category==="container")&&traverseContainerWidgets(e.widgetList,d)})}function traverseAllWidgets(t,d){!t||t.map(e=>{d(e),e.type==="grid"?e.cols.map(h=>{d(h),traverseAllWidgets(h.widgetList,d)}):e.type==="table"?e.rows.map(h=>{h.cols.map(m=>{d(m),traverseAllWidgets(m.widgetList,d)})}):e.type==="tab"?e.tabs.map(h=>{traverseAllWidgets(h.widgetList,d)}):(e.type==="sub-form"||e.category==="container")&&traverseAllWidgets(e.widgetList,d)})}function handleWidgetForTraverse(t,d){t.category?traverseFieldWidgetsOfContainer(t,d):t.formItemFlag&&d(t)}function traverseFieldWidgetsOfContainer(t,d){t.type==="grid"?t.cols.forEach(e=>{e.widgetList.forEach(h=>{handleWidgetForTraverse(h,d)})}):t.type==="table"?t.rows.forEach(e=>{e.cols.forEach(h=>{h.widgetList.forEach(m=>{handleWidgetForTraverse(m,d)})})}):t.type==="tab"?t.tabs.forEach(e=>{e.widgetList.forEach(h=>{handleWidgetForTraverse(h,d)})}):t.type==="sub-form"?t.widgetList.forEach(e=>{handleWidgetForTraverse(e,d)}):t.category==="container"&&t.widgetList.forEach(e=>{handleWidgetForTraverse(e,d)})}function getAllFieldWidgets(t){if(!t)return[];let d=[];return traverseFieldWidgets(t,h=>{d.push({type:h.type,name:h.options.name,field:h})}),d}function getAllContainerWidgets(t){if(!t)return[];let d=[];return traverseContainerWidgets(t,h=>{d.push({type:h.type,name:h.options.name,container:h})}),d}function copyToClipboard(t,d,e,h,m){const g=new Clipboard(d.target,{text:()=>t});g.on("success",()=>{e.success(h),g.destroy()}),g.on("error",()=>{e.error(m),g.destroy()}),g.onClick(d)}function getQueryParam(t){let e=window.location.search.substring(1).split("&");for(let h=0;h{h=isDef(h)&&isDef(h[m])?h[m]:null}),h}let locale=require$$0$1.reactive({lang:localStorage.getItem("v_form_locale")||"zh-CN"});function createI18n(t){return{messages:t.messages,$st(d,...e){const h=get(this.messages[locale.lang],d);return typeof h=="function"?h(...e):h!==null?h:d},$st2(d,e){let h=this.messages[locale.lang];const m=get(h,d);return m!==null?m:get(h,e)},setLang(d){locale.lang=d}}}var enLocale={application:{"zh-CN":"\u7B80\u4F53\u4E2D\u6587","en-US":"English",productTitle:"Online Form Designer",github:"GitHub",document:"Docs",qqGroup:"WeChat Group",deployment:"Deployment",subscription:"Subscription"},designer:{componentLib:"Components",formLib:"Templates",containerTitle:"Container",dragHandlerHint:"drag container or field to layout center",dragAction:"drag",basicFieldTitle:"Basic Field",advancedFieldTitle:"Advanced Field",customFieldTitle:"Customized Field",noWidgetHint:"Please select a widget from the left list, drag and drop to this container.",widgetLabel:{grid:"Grid",table:"Table",tab:"Tab",section:"Section","sub-form":"SubForm","grid-col":"GridCol","table-cell":"TableCell","tab-pane":"TabPane","data-table":"DataTable",input:"Input",textarea:"Textarea",number:"InputNumber",radio:"Radio",checkbox:"Checkbox",select:"Select",time:"Time","time-range":"Time range",date:"Date","date-range":"Date range",switch:"Switch",rate:"Rate",color:"ColorPicker",slider:"Slider","static-text":"Text","html-text":"HTML",button:"Button",divider:"Divider","picture-upload":"Picture","file-upload":"File","rich-editor":"Rich Editor",cascader:"Cascader",slot:"Slot",custom:"Custom Component"},hint:{selectParentWidget:"Select parent of this widget",moveUpWidget:"Move up this widget",moveDownWidget:"Move down this widget",cloneWidget:"Clone this widget",insertRow:"Insert new row",insertColumn:"Insert new column",remove:"Remove this widget",cellSetting:"Cell setting",dragHandler:"Drag handler",copyField:"Copy field widget",onlyFieldWidgetAcceptable:"Only field widget can be dragged into sub-form",moveUpFirstChildHint:"First child can not be move up",moveDownLastChildHint:"Last child can not be move down",closePreview:"Close",copyJson:"Copy",saveFormJson:"Save As File",copyVueCode:"Copy Vue Code",copyHtmlCode:"Copy HTML Code",copyJsonSuccess:"Copy succeed",importJsonSuccess:"Import succeed",invalidJsonFormat:"Invalid JSON format",jsonVersionMismatch:"Version of JSON mismatch",copyJsonFail:"Copy failed",copyVueCodeSuccess:"Copy succeed",copyVueCodeFail:"Copy failed",copyHtmlCodeSuccess:"Copy succeed",copyHtmlCodeFail:"Copy failed",saveVueCode:"Save Vue File",saveHtmlCode:"Save Html File",getFormData:"Get Data",resetForm:"Reset",disableForm:"Disable",enableForm:"Enable",exportFormData:"Form Data",copyFormData:"Copy",saveFormData:"Save As File",copyVue2SFC:"Copy Vue2",copyVue3SFC:"Copy Vue3",copySFCFail:"Copy failed",copySFCSuccess:"Copy succeed",saveVue2SFC:"Save As Vue2",saveVue3SFC:"Save As Vue3",fileNameForSave:"File name:",saveFileTitle:"Save as File",fileNameInputPlaceholder:"Enter the file name",sampleLoadedSuccess:"Example loaded successfully",sampleLoadedFail:"Sample load failed",loadFormTemplate:"Load This",loadFormTemplateHint:"Are you sure to load this template?",loadFormTemplateSuccess:"Load form template success!",loadFormTemplateFailed:"Load form template failed.",currentNodeCannotBeSelected:"The current node cannot be selected.",widgetSetting:"Widget Config",formSetting:"Form Config",prompt:"Prompt",confirm:"OK",cancel:"Cancel",import:"Import",importJsonHint:"The code to be imported should have the following JSON format.",invalidOptionsData:"Invalid data of options:",lastPaneCannotBeDeleted:"The last pane cannot be deleted.",duplicateName:"Duplicate name: ",nameRequired:"Name required.",numberValidator:"Number",letterValidator:"Letter",letterAndNumberValidator:"LetterAndNumber",mobilePhoneValidator:"MobilePhone",emailValidator:"Email",urlValidator:"URL",noChineseValidator:"Non-Chinese",chineseValidator:"Chinese",rowspanNotConsistentForMergeEntireRow:"Cells in this row don't have the same rowspan, operation failed.",colspanNotConsistentForMergeEntireColumn:"Cells in this column don't have the same colspan, operation failed.",rowspanNotConsistentForDeleteEntireRow:"Cells in this row don't have the same rowspan, operation failed.",colspanNotConsistentForDeleteEntireColumn:"Cells in this column don't have the same colspan, operation failed.",lastColCannotBeDeleted:"The last col cannot be deleted.",lastRowCannotBeDeleted:"The last row cannot be deleted."},toolbar:{undoHint:"Undo",redoHint:"Redo",pcLayout:"PC",padLayout:"Pad",mobileLayout:"H5",nodeTreeHint:"Tree View Of Component Hierarchy",nodeTreeTitle:"Tree View Of Component Hierarchy",clear:"Clear",preview:"Preview",importJson:"Import",exportJson:"Export",exportCode:"Codes",generateCode:"Generate Code",generateSFC:"Generate SFC"},setting:{basicSetting:"Basic Setting",attributeSetting:"Attribute Setting",commonSetting:"Common Setting",advancedSetting:"Advanced Setting",eventSetting:"Event Setting",uniqueName:"Unique Name",editNameHelp:"Press enter to confirm the modification",label:"Label",displayType:"Type",defaultValue:"Default Value",placeholder:"Placeholder",startPlaceholder:"Start Placeholder",endPlaceholder:"End Placeholder",widgetColumnWidth:"Width",widgetSize:"Size",fontSize:"Font Size",textAlign:"Text Align",autoFullWidth:"Auto Full Width",showStops:"Show Stops",displayStyle:"Display Style",inlineLayout:"inline",blockLayout:"block",buttonStyle:"Show As Button",border:"Show Border",labelWidth:"Width Of Label",rows:"Rows",labelHidden:"Hide Label",required:"Required",requiredHint:"Failure Hint",validation:"Validation",validationHelp:"Regular expressions supported",validationHint:"Validation Hint",readonly:"Readonly",disabled:"Disabled",hidden:"Hidden",textContent:"Text",preWrap:"Line Wrap",htmlContent:"HTML",clearable:"Clearable",editable:"Editable",format:"Format",valueFormat:"Value Format",showPassword:"Show Reveal",filterable:"Filterable",allowCreate:"Allow Create",remote:"Remote Query",automaticDropdown:"Automatic Dropdown",multiple:"Multiple",multipleLimit:"Multiple Limit",checkStrictly:"Any Level Selectable",showAllLevels:"Show All Levels",contentPosition:"Content Position",plain:"Plain",round:"Round",circle:"Circle",icon:"Icon",optionsSetting:"Options Setting",addOption:"Add Option",importOptions:"Import Options",resetDefault:"Reset Default",uploadSetting:"Upload Setting",uploadURL:"Upload URL",uploadTip:"Tip Content",withCredentials:"Send Cookie",multipleSelect:"File Multi-select",showFileList:"Show File List",limit:"Max Upload Number",fileMaxSize:"Max Size(MB)",fileTypes:"Upload File Types",fileTypesHelp:"Allows to add more file types",headers:"Request Headers",cellWidth:"Width",cellHeight:"Height",wordBreak:"Line Wrap",gridColHeight:"Height Of Col(px)",gutter:"Gutter(px)",columnSetting:"Cols Setting",colsOfGrid:"Cols Of Grid:",colSpanTitle:"Spans Of Col",colOffsetTitle:"Offset Of Col",colPushTitle:"Push Of Col",colPullTitle:"Pull Of Col",addColumn:"Add Column",responsive:"Responsive",tabPaneSetting:"Tab Panes",addTabPane:"Add Tab Pane",paneActive:"Active",customLabelIcon:"Custom Label",labelIconClass:"Label Icon Class",labelIconPosition:"Label Icon Position",labelTooltip:"Label Tooltip",minValue:"Min Value",maxValue:"Max Value",precision:"Precision",step:"Step",controlsPosition:"Controls Position",minLength:"Min Length",maxLength:"Max Length",showWordLimit:"Show Word Limit",prefixIcon:"Prefix Icon",suffixIcon:"Suffix Icon",inputButton:"Input Button Setting",appendButton:"Append Button",appendButtonDisabled:"Button Disabled",appendButtonIcon:"Append Button Icon",buttonIcon:"Button Icon",switchWidth:"Width of Switch(px)",activeText:"Active Text",inactiveText:"Inactive Text",activeColor:"Active Color",inactiveColor:"Inactive Color",maxStars:"Stars Max Number",lowThreshold:"Low Threshold",highThreshold:"High Threshold",allowHalf:"Allow Half",showText:"Show Text",showScore:"Show Score",range:"Range",vertical:"Vertical",showBlankRow:"Show Blank Row",showRowNumber:"Show Row Number",contentHeight:"Content Area Height",insertColumnToLeft:"insert column to left",insertColumnToRight:"insert column to right",insertRowAbove:"insert row above",insertRowBelow:"insert row below",mergeLeftColumn:"merge left cell",mergeRightColumn:"merge right cell",mergeEntireRow:"merge entire row",mergeRowAbove:"merge cell above",mergeRowBelow:"merge cell below",mergeEntireColumn:"merge entire column",undoMergeCol:"undo merge column",undoMergeRow:"undo merge row",deleteEntireCol:"delete entire column",deleteEntireRow:"delete entire row",widgetName:"Unique Name",formSize:"Size",labelPosition:"Position Of Label",topPosition:"Top",leftPosition:"Left",labelAlign:"Label Align",leftAlign:"Left",centerAlign:"Center",rightAlign:"Right",formCss:"Form CSS",addCss:"Edit",customClass:"Custom Class",globalFunctions:"Global Functions",addEventHandler:"Edit",editWidgetEventHandler:"Edit Widget Event Handler",editFormEventHandler:"Edit Form Event Handler",formSFCSetting:"SFC Setting",formModelName:"Model Name",formRefName:"Ref Name",formRulesName:"Rules Name",syntaxCheckWarning:"Syntax error in the javascript codes, please check again!"}}},zhLocale={application:{"zh-CN":"\u7B80\u4F53\u4E2D\u6587","en-US":"English",productTitle:"\u8868\u5355\u8BBE\u8BA1\u5668",github:"GitHub",document:"\u6587\u6863",qqGroup:"\u6280\u672FWX\u7FA4",deployment:"\u79C1\u6709\u90E8\u7F72",subscription:"\u8BA2\u9605Pro"},designer:{componentLib:"\u7EC4\u4EF6\u5E93",formLib:"\u8868\u5355\u6A21\u677F",containerTitle:"\u5BB9\u5668",dragHandlerHint:"\u9F20\u6807\u62D6\u62FD\u5BB9\u5668\u7EC4\u4EF6\u6216\u5B57\u6BB5\u7EC4\u4EF6\u5E76\u653E\u7F6E\u4E8E\u8868\u5355\u4E2D",dragAction:"\u62D6\u52A8",basicFieldTitle:"\u57FA\u7840\u5B57\u6BB5",advancedFieldTitle:"\u9AD8\u7EA7\u5B57\u6BB5",customFieldTitle:"\u81EA\u5B9A\u4E49\u6269\u5C55\u5B57\u6BB5",noWidgetHint:"\u8BF7\u4ECE\u5DE6\u4FA7\u5217\u8868\u4E2D\u9009\u62E9\u4E00\u4E2A\u7EC4\u4EF6, \u7136\u540E\u7528\u9F20\u6807\u62D6\u52A8\u7EC4\u4EF6\u653E\u7F6E\u4E8E\u6B64\u5904.",widgetLabel:{grid:"\u6805\u683C",table:"\u8868\u683C",tab:"\u6807\u7B7E\u9875",section:"\u533A\u5757","sub-form":"\u5B50\u8868\u5355","grid-col":"\u6805\u683C\u5217","table-cell":"\u5355\u5143\u683C","tab-pane":"\u9009\u9879\u5361\u9875","data-table":"\u6570\u636E\u8868\u683C",input:"\u5355\u884C\u8F93\u5165",textarea:"\u591A\u884C\u8F93\u5165",number:"\u8BA1\u6570\u5668",radio:"\u5355\u9009\u9879",checkbox:"\u591A\u9009\u9879",select:"\u4E0B\u62C9\u9009\u9879",time:"\u65F6\u95F4","time-range":"\u65F6\u95F4\u8303\u56F4",date:"\u65E5\u671F","date-range":"\u65E5\u671F\u8303\u56F4",switch:"\u5F00\u5173",rate:"\u8BC4\u5206",color:"\u989C\u8272\u9009\u62E9\u5668",slider:"\u6ED1\u5757","static-text":"\u9759\u6001\u6587\u5B57","html-text":"HTML",button:"\u6309\u94AE",divider:"\u5206\u9694\u7EBF","picture-upload":"\u56FE\u7247","file-upload":"\u6587\u4EF6","rich-editor":"\u5BCC\u6587\u672C",cascader:"\u7EA7\u8054\u9009\u62E9",slot:"\u63D2\u69FD",custom:"Custom Component"},hint:{selectParentWidget:"\u9009\u4E2D\u7236\u7EC4\u4EF6",moveUpWidget:"\u4E0A\u79FB\u7EC4\u4EF6",moveDownWidget:"\u4E0B\u79FB\u7EC4\u4EF6",cloneWidget:"\u590D\u5236\u7EC4\u4EF6",insertRow:"\u63D2\u5165\u65B0\u884C",insertColumn:"\u63D2\u5165\u65B0\u5217",remove:"\u79FB\u9664\u7EC4\u4EF6",cellSetting:"\u5355\u5143\u683C\u64CD\u4F5C",dragHandler:"\u62D6\u62FD\u624B\u67C4",copyField:"\u590D\u5236\u5B57\u6BB5\u7EC4\u4EF6",onlyFieldWidgetAcceptable:"\u5B50\u8868\u5355\u53EA\u80FD\u63A5\u6536\u5B57\u6BB5\u7EC4\u4EF6",moveUpFirstChildHint:"\u5DF2\u7ECF\u79FB\u52A8\u5230\u6700\u4E0A\u9762",moveDownLastChildHint:"\u5DF2\u7ECF\u79FB\u52A8\u5230\u6700\u4E0B\u9762",closePreview:"\u5173\u95ED",copyJson:"\u590D\u5236JSON",saveFormJson:"\u4FDD\u5B58\u4E3A\u6587\u4EF6",copyVueCode:"\u590D\u5236Vue\u4EE3\u7801",copyHtmlCode:"\u590D\u5236HTML\u4EE3\u7801",copyJsonSuccess:"\u590D\u5236JSON\u6210\u529F",importJsonSuccess:"\u5BFC\u5165JSON\u6210\u529F",invalidJsonFormat:"\u65E0\u6548\u7684\u8868\u5355JSON\u683C\u5F0F",jsonVersionMismatch:"\u8868\u5355JSON\u7248\u672C\u53F7\u4E0D\u5339\u914D",copyJsonFail:"\u590D\u5236JSON\u5931\u8D25",copyVueCodeSuccess:"\u590D\u5236Vue\u4EE3\u7801\u6210\u529F",copyVueCodeFail:"\u590D\u5236Vue\u4EE3\u7801\u5931\u8D25",copyHtmlCodeSuccess:"\u590D\u5236HTML\u4EE3\u7801\u6210\u529F",copyHtmlCodeFail:"\u590D\u5236HTML\u4EE3\u7801\u5931\u8D25",saveVueCode:"\u4FDD\u5B58Vue\u6587\u4EF6",saveHtmlCode:"\u4FDD\u5B58Html\u6587\u4EF6",getFormData:"\u83B7\u53D6\u6570\u636E",resetForm:"\u91CD\u7F6E\u8868\u5355",disableForm:"\u7981\u7528\u7F16\u8F91",enableForm:"\u6062\u590D\u7F16\u8F91",exportFormData:"\u8868\u5355\u6570\u636E",copyFormData:"\u590D\u5236JSON",saveFormData:"\u4FDD\u5B58\u4E3A\u6587\u4EF6",copyVue2SFC:"\u590D\u5236Vue2\u4EE3\u7801",copyVue3SFC:"\u590D\u5236Vue3\u4EE3\u7801",copySFCFail:"\u590D\u5236SFC\u4EE3\u7801\u5931\u8D25",copySFCSuccess:"\u590D\u5236SFC\u4EE3\u7801\u6210\u529F",saveVue2SFC:"\u4FDD\u5B58\u4E3AVue2\u7EC4\u4EF6",saveVue3SFC:"\u4FDD\u5B58\u4E3AVue3\u7EC4\u4EF6",fileNameForSave:"\u6587\u4EF6\u540D\uFF1A",saveFileTitle:"\u4FDD\u5B58\u4E3A\u6587\u4EF6",fileNameInputPlaceholder:"\u8BF7\u8F93\u5165\u6587\u4EF6\u540D",sampleLoadedSuccess:"\u8868\u5355\u793A\u4F8B\u52A0\u8F7D\u6210\u529F",sampleLoadedFail:"\u8868\u5355\u793A\u4F8B\u52A0\u8F7D\u5931\u8D25",loadFormTemplate:"\u52A0\u8F7D\u6B64\u6A21\u677F",loadFormTemplateHint:"\u662F\u5426\u52A0\u8F7D\u8FD9\u4E2A\u6A21\u677F\uFF1F\u52A0\u8F7D\u540E\u4F1A\u8986\u76D6\u8BBE\u8BA1\u5668\u5F53\u524D\u8868\u5355\uFF0C\u4F60\u53EF\u4EE5\u4F7F\u7528\u201C\u64A4\u9500\u201D\u529F\u80FD\u6062\u590D\u3002",loadFormTemplateSuccess:"\u8868\u5355\u6A21\u677F\u52A0\u8F7D\u6210\u529F",loadFormTemplateFailed:"\u8868\u5355\u6A21\u677F\u52A0\u8F7D\u5931\u8D25",currentNodeCannotBeSelected:"\u5F53\u524D\u7EC4\u4EF6\u8282\u70B9\u4E0D\u53EF\u9009\u62E9",widgetSetting:"\u7EC4\u4EF6\u8BBE\u7F6E",formSetting:"\u8868\u5355\u8BBE\u7F6E",prompt:"\u63D0\u793A",confirm:"\u786E\u5B9A",cancel:"\u53D6\u6D88",import:"\u5BFC\u5165",importJsonHint:"\u5BFC\u5165\u7684JSON\u5185\u5BB9\u987B\u7B26\u5408\u4E0B\u8FF0\u683C\u5F0F\uFF0C\u4EE5\u4FDD\u8BC1\u987A\u5229\u5BFC\u5165.",invalidOptionsData:"\u65E0\u6548\u7684\u9009\u9879\u6570\u636E:",lastPaneCannotBeDeleted:"\u4EC5\u5269\u4E00\u4E2A\u9009\u9879\u5361\u9875\u4E0D\u53EF\u5220\u9664.",duplicateName:"\u7EC4\u4EF6\u540D\u79F0\u5DF2\u5B58\u5728: ",nameRequired:"\u7EC4\u4EF6\u540D\u79F0\u4E0D\u53EF\u4E3A\u7A7A",numberValidator:"\u6570\u5B57",letterValidator:"\u5B57\u6BCD",letterAndNumberValidator:"\u6570\u5B57\u5B57\u6BCD",mobilePhoneValidator:"\u624B\u673A\u53F7\u7801",emailValidator:"\u90AE\u7BB1",urlValidator:"\u7F51\u5740",noChineseValidator:"\u975E\u4E2D\u6587\u5B57\u7B26",chineseValidator:"\u4EC5\u4E2D\u6587\u5B57\u7B26",rowspanNotConsistentForMergeEntireRow:"\u5B58\u5728\u884C\u9AD8\u4E0D\u4E00\u81F4\u7684\u5355\u5143\u683C, \u65E0\u6CD5\u5408\u5E76\u6574\u884C.",colspanNotConsistentForMergeEntireColumn:"\u5B58\u5728\u5217\u5BBD\u4E0D\u4E00\u81F4\u7684\u5355\u5143\u683C, \u65E0\u6CD5\u5408\u5E76\u6574\u5217.",rowspanNotConsistentForDeleteEntireRow:"\u5B58\u5728\u884C\u9AD8\u4E0D\u4E00\u81F4\u7684\u5355\u5143\u683C, \u4E0D\u53EF\u5220\u9664\u6574\u884C.",colspanNotConsistentForDeleteEntireColumn:"\u5B58\u5728\u5217\u5BBD\u4E0D\u4E00\u81F4\u7684\u5355\u5143\u683C, \u4E0D\u53EF\u5220\u9664\u6574\u5217.",lastColCannotBeDeleted:"\u6700\u540E\u4E00\u5217\u4E0D\u53EF\u5220\u9664.",lastRowCannotBeDeleted:"\u6700\u540E\u4E00\u884C\u4E0D\u53EF\u5220\u9664."},toolbar:{undoHint:"\u64A4\u9500",redoHint:"\u91CD\u505A",pcLayout:"PC",padLayout:"Pad",mobileLayout:"H5",nodeTreeHint:"\u7EC4\u4EF6\u5C42\u6B21\u7ED3\u6784\u6811",nodeTreeTitle:"\u7EC4\u4EF6\u5C42\u6B21\u7ED3\u6784\u6811",clear:"\u6E05\u7A7A",preview:"\u9884\u89C8",importJson:"\u5BFC\u5165JSON",exportJson:"\u5BFC\u51FAJSON",exportCode:"\u5BFC\u51FA\u4EE3\u7801",generateCode:"\u751F\u6210\u4EE3\u7801",generateSFC:"\u751F\u6210SFC"},setting:{basicSetting:"\u57FA\u672C\u5C5E\u6027",attributeSetting:"\u5C5E\u6027\u8BBE\u7F6E",commonSetting:"\u5E38\u89C1\u5C5E\u6027",advancedSetting:"\u9AD8\u7EA7\u5C5E\u6027",eventSetting:"\u4E8B\u4EF6\u5C5E\u6027",uniqueName:"\u552F\u4E00\u540D\u79F0",editNameHelp:"\u4FEE\u6539\u540D\u79F0\u540E\u9700\u6309\u56DE\u8F66\u786E\u8BA4",label:"\u6807\u7B7E",displayType:"\u663E\u793A\u7C7B\u578B",defaultValue:"\u9ED8\u8BA4\u503C",placeholder:"\u5360\u4F4D\u5185\u5BB9",startPlaceholder:"\u8D77\u59CB\u5360\u4F4D\u5185\u5BB9",endPlaceholder:"\u622A\u6B62\u5360\u4F4D\u5185\u5BB9",widgetColumnWidth:"\u7EC4\u4EF6\u5217\u5BBD",widgetSize:"\u7EC4\u4EF6\u5927\u5C0F",fontSize:"\u5B57\u4F53\u5927\u5C0F",textAlign:"\u6587\u5B57\u5BF9\u9F50",autoFullWidth:"\u81EA\u52A8\u62C9\u4F38\u5BBD\u5EA6",showStops:"\u663E\u793A\u95F4\u65AD\u70B9",displayStyle:"\u663E\u793A\u6837\u5F0F",inlineLayout:"\u884C\u5185",blockLayout:"\u5757",buttonStyle:"\u663E\u793A\u4E3A\u6309\u94AE",border:"\u5E26\u6709\u8FB9\u6846",labelWidth:"\u6807\u7B7E\u5BBD\u5EA6",rows:"\u884C\u6570",labelHidden:"\u9690\u85CF\u5B57\u6BB5\u6807\u7B7E",required:"\u5FC5\u586B\u5B57\u6BB5",requiredHint:"\u5FC5\u586B\u6821\u9A8C\u63D0\u793A",validation:"\u5B57\u6BB5\u6821\u9A8C",validationHelp:"\u652F\u6301\u8F93\u5165\u6B63\u5219\u8868\u8FBE\u5F0F",validationHint:"\u6821\u9A8C\u5931\u8D25\u63D0\u793A",readonly:"\u53EA\u8BFB",disabled:"\u7981\u7528",hidden:"\u9690\u85CF",textContent:"\u9759\u6001\u6587\u5B57",preWrap:"\u81EA\u52A8\u6362\u884C",htmlContent:"HTML",clearable:"\u53EF\u6E05\u9664",editable:"\u53EF\u8F93\u5165",format:"\u663E\u793A\u683C\u5F0F",valueFormat:"\u7ED1\u5B9A\u503C\u683C\u5F0F",showPassword:"\u53EF\u663E\u793A\u5BC6\u7801",filterable:"\u53EF\u641C\u7D22\u9009\u9879",allowCreate:"\u5141\u8BB8\u521B\u5EFA\u9009\u9879",remote:"\u53EF\u8FDC\u7A0B\u641C\u7D22",automaticDropdown:"\u81EA\u52A8\u5F39\u51FA\u9009\u9879",multiple:"\u9009\u9879\u53EF\u591A\u9009",multipleLimit:"\u591A\u9009\u6570\u91CF\u9650\u5236",checkStrictly:"\u4EFB\u610F\u7EA7\u8282\u70B9\u53EF\u9009",showAllLevels:"\u663E\u793A\u5B8C\u6574\u8DEF\u5F84",contentPosition:"\u6587\u5B57\u4F4D\u7F6E",plain:"\u6734\u7D20\u6309\u94AE",round:"\u5706\u89D2\u6309\u94AE",circle:"\u5706\u5F62\u6309\u94AE",icon:"\u56FE\u6807",optionsSetting:"\u9009\u9879\u8BBE\u7F6E",addOption:"\u589E\u52A0\u9009\u9879",importOptions:"\u5BFC\u5165\u9009\u9879",resetDefault:"\u91CD\u8BBE\u9009\u4E2D\u9879",uploadSetting:"\u4E0A\u4F20\u53C2\u6570\u8BBE\u7F6E",uploadURL:"\u4E0A\u4F20\u5730\u5740",uploadTip:"\u4E0A\u4F20\u63D0\u793A\u5185\u5BB9",withCredentials:"\u53D1\u9001cookie\u51ED\u8BC1",multipleSelect:"\u6587\u4EF6\u53EF\u591A\u9009",showFileList:"\u663E\u793A\u6587\u4EF6\u5217\u8868",limit:"\u6700\u5927\u4E0A\u4F20\u6570\u91CF",fileMaxSize:"\u6587\u4EF6\u5927\u5C0F\u9650\u5236(MB)",fileTypes:"\u4E0A\u4F20\u6587\u4EF6\u7C7B\u578B",fileTypesHelp:"\u652F\u6301\u6DFB\u52A0\u5176\u4ED6\u6587\u4EF6\u7C7B\u578B",headers:"\u4E0A\u4F20\u8BF7\u6C42\u5934",cellWidth:"\u5BBD\u5EA6",cellHeight:"\u9AD8\u5EA6",wordBreak:"\u6587\u5B57\u81EA\u52A8\u6362\u884C",gridColHeight:"\u6805\u683C\u5217\u7EDF\u4E00\u9AD8\u5EA6(px)",gutter:"\u6805\u683C\u95F4\u9694(px)",columnSetting:"\u6805\u683C\u5C5E\u6027\u8BBE\u7F6E",colsOfGrid:"\u5F53\u524D\u6805\u683C\u5217:",colSpanTitle:"\u6805\u683C\u5BBD\u5EA6",colOffsetTitle:"\u5DE6\u4FA7\u95F4\u9694\u683C\u6570",colPushTitle:"\u53F3\u79FB\u6805\u683C\u6570",colPullTitle:"\u5DE6\u79FB\u6805\u683C\u6570",addColumn:"\u589E\u52A0\u6805\u683C",responsive:"\u54CD\u5E94\u5F0F\u5E03\u5C40",tabPaneSetting:"\u9009\u9879\u5361\u8BBE\u7F6E",addTabPane:"\u589E\u52A0\u9009\u9879\u5361\u9875",paneActive:"\u6FC0\u6D3B",customLabelIcon:"\u5B9A\u5236\u5B57\u6BB5\u6807\u7B7E",labelIconClass:"\u6807\u7B7EIcon\u6837\u5F0F",labelIconPosition:"\u6807\u7B7EIcon\u4F4D\u7F6E",labelTooltip:"\u6807\u7B7E\u6587\u5B57\u63D0\u793A",minValue:"\u6700\u5C0F\u503C",maxValue:"\u6700\u5927\u503C",precision:"\u7CBE\u5EA6",step:"\u589E\u51CF\u6B65\u957F",controlsPosition:"\u63A7\u5236\u6309\u94AE\u4F4D\u7F6E",minLength:"\u6700\u5C0F\u957F\u5EA6",maxLength:"\u6700\u5927\u957F\u5EA6",showWordLimit:"\u663E\u793A\u5B57\u6570\u7EDF\u8BA1",prefixIcon:"\u5934\u90E8Icon",suffixIcon:"\u5C3E\u90E8Icon",inputButton:"\u8F93\u5165\u6846\u6309\u94AE\u8BBE\u7F6E",appendButton:"\u6DFB\u52A0\u540E\u7F6E\u6309\u94AE",appendButtonDisabled:"\u540E\u7F6E\u6309\u94AE\u7981\u7528",appendButtonIcon:"\u540E\u7F6E\u6309\u94AEIcon",buttonIcon:"\u6309\u94AEIcon",switchWidth:"\u5F00\u5173\u5BBD\u5EA6\uFF08\u50CF\u7D20\uFF09",activeText:"\u5F00\u542F\u65F6\u6587\u5B57\u63CF\u8FF0",inactiveText:"\u5173\u95ED\u65F6\u6587\u5B57\u63CF\u8FF0",activeColor:"\u5F00\u542F\u65F6\u80CC\u666F\u8272",inactiveColor:"\u5173\u95ED\u65F6\u80CC\u666F\u8272",maxStars:"\u6700\u5927\u8BC4\u5206\u503C",lowThreshold:"\u4F4E\u5206\u754C\u9650\u503C",highThreshold:"\u9AD8\u5206\u754C\u9650\u503C",allowHalf:"\u5141\u8BB8\u534A\u9009",showText:"\u663E\u793A\u8F85\u52A9\u6587\u5B57",showScore:"\u663E\u793A\u5F53\u524D\u5206\u6570",range:"\u662F\u5426\u4E3A\u8303\u56F4\u9009\u62E9",vertical:"\u662F\u5426\u7AD6\u5411\u663E\u793A",showBlankRow:"\u9ED8\u8BA4\u663E\u793A\u65B0\u884C",showRowNumber:"\u663E\u793A\u884C\u53F7",contentHeight:"\u5185\u5BB9\u533A\u9AD8\u5EA6",insertColumnToLeft:"\u63D2\u5165\u5DE6\u4FA7\u5217",insertColumnToRight:"\u63D2\u5165\u53F3\u4FA7\u5217",insertRowAbove:"\u63D2\u5165\u4E0A\u65B9\u884C",insertRowBelow:"\u63D2\u5165\u4E0B\u65B9\u884C",mergeLeftColumn:"\u5408\u5E76\u5DE6\u4FA7\u5355\u5143\u683C",mergeRightColumn:"\u5408\u5E76\u53F3\u4FA7\u5355\u5143\u683C",mergeEntireRow:"\u5408\u5E76\u6574\u884C",mergeRowAbove:"\u5408\u5E76\u4E0A\u65B9\u5355\u5143\u683C",mergeRowBelow:"\u5408\u5E76\u4E0B\u65B9\u5355\u5143\u683C",mergeEntireColumn:"\u5408\u5E76\u6574\u5217",undoMergeCol:"\u64A4\u9500\u5217\u5408\u5E76",undoMergeRow:"\u64A4\u9500\u884C\u5408\u5E76",deleteEntireCol:"\u5220\u9664\u6574\u5217",deleteEntireRow:"\u5220\u9664\u6574\u884C",widgetName:"\u7EC4\u4EF6\u552F\u4E00\u540D\u79F0",formSize:"\u5168\u5C40\u7EC4\u4EF6\u5927\u5C0F",labelPosition:"\u6807\u7B7E\u4F4D\u7F6E",topPosition:"\u9876\u90E8",leftPosition:"\u5DE6\u8FB9",labelAlign:"\u5B57\u6BB5\u6807\u7B7E\u5BF9\u9F50",leftAlign:"\u5C45\u5DE6",centerAlign:"\u5C45\u4E2D",rightAlign:"\u5C45\u53F3",formCss:"\u8868\u5355\u5168\u5C40CSS",addCss:"\u7F16\u5199CSS",customClass:"\u81EA\u5B9A\u4E49CSS\u6837\u5F0F",globalFunctions:"\u8868\u5355\u5168\u5C40\u51FD\u6570",addEventHandler:"\u7F16\u5199\u4EE3\u7801",editWidgetEventHandler:"\u7EC4\u4EF6\u4E8B\u4EF6\u5904\u7406",editFormEventHandler:"\u8868\u5355\u4E8B\u4EF6\u5904\u7406",formSFCSetting:"\u751F\u6210SFC\u8BBE\u7F6E",formModelName:"\u6570\u636E\u5BF9\u8C61\u540D\u79F0",formRefName:"\u5F15\u7528\u540D\u79F0",formRulesName:"\u9A8C\u8BC1\u89C4\u5219\u540D\u79F0",syntaxCheckWarning:"JS\u4EE3\u7801\u5B58\u5728\u8BED\u6CD5\u9519\u8BEF\uFF0C\u8BF7\u4ED4\u7EC6\u68C0\u67E5\uFF01"}}},enLocale_render={render:{hint:{prompt:"Prompt",confirm:"OK",cancel:"Cancel",selectPlaceholder:"Pick some item",timePlaceholder:"Select time",startTimePlaceholder:"Start time",endTimePlaceholder:"End time",datePlaceholder:"Select date",startDatePlaceholder:"Start date",endDatePlaceholder:"End date",blankCellContent:"--",uploadError:"Upload error: ",uploadExceed:"The maximum number(${uploadLimit}) of file uploads has been exceeded.",unsupportedFileType:"Unsupported format: ",fileSizeExceed:"File size out of limit: ",refNotFound:"Ref not found: ",fieldRequired:"Input value should be not null.",invalidNumber:"Invalid number format",selectFile:" File...",downloadFile:"Download",removeFile:"Remove",validationFailed:"Form validation failed",subFormAction:"Action",subFormAddAction:"Add",subFormAddActionHint:"add new row",insertSubFormRow:"insert new row",deleteSubFormRow:"delete this row",nonSubFormType:"The type of widget don't match sub-form"}}},zhLocale_render={render:{hint:{prompt:"\u63D0\u793A",confirm:"\u786E\u5B9A",cancel:"\u53D6\u6D88",selectPlaceholder:"\u8BF7\u9009\u62E9",timePlaceholder:"\u9009\u62E9\u65F6\u95F4",startTimePlaceholder:"\u8D77\u59CB\u65F6\u95F4",endTimePlaceholder:"\u622A\u6B62\u65F6\u95F4",datePlaceholder:"\u9009\u62E9\u65E5\u671F",startDatePlaceholder:"\u8D77\u59CB\u65E5\u671F",endDatePlaceholder:"\u622A\u6B62\u65E5\u671F",blankCellContent:"--",uploadError:"\u4E0A\u4F20\u9519\u8BEF: ",uploadExceed:"\u6700\u5927\u4E0A\u4F20\u6570\u91CF(${uploadLimit})\u5DF2\u8D85\u51FA.",unsupportedFileType:"\u4E0D\u652F\u6301\u683C\u5F0F: ",fileSizeExceed:"\u6587\u4EF6\u5927\u5C0F\u5DF2\u8D85\u51FA: ",refNotFound:"\u7EC4\u4EF6\u672A\u627E\u5230: ",fieldRequired:"\u5B57\u6BB5\u503C\u4E0D\u53EF\u4E3A\u7A7A",invalidNumber:"\u6570\u636E\u683C\u5F0F\u9519\u8BEF",selectFile:" \u9009\u62E9\u6587\u4EF6",downloadFile:"\u4E0B\u8F7D",removeFile:"\u79FB\u9664",validationFailed:"\u8868\u5355\u6570\u636E\u6821\u9A8C\u5931\u8D25",subFormAction:"\u64CD\u4F5C",subFormAddAction:"\u65B0\u589E",subFormAddActionHint:"\u65B0\u589E\u884C",insertSubFormRow:"\u63D2\u5165\u884C",deleteSubFormRow:"\u5220\u9664\u884C",nonSubFormType:"\u7EC4\u4EF6\u7C7B\u578B\u4E0D\u662F\u5B50\u8868\u5355"}}},enLocale_extension={extension:{widgetLabel:{card:"Card",alert:"Alert"},setting:{cardFolded:"Folded",cardShowFold:"Show Fold",cardWidth:"Width Of Card",cardShadow:"Shadow",alertTitle:"Title",alertType:"Type",description:"Description",closable:"Closable",closeText:"Text On Close Btn",center:"Center",showIcon:"Show Icon",effect:"Effect"}}},zhLocale_extension={extension:{widgetLabel:{card:"\u5361\u7247",alert:"\u63D0\u793A"},setting:{cardFolded:"\u662F\u5426\u6536\u8D77",cardShowFold:"\u663E\u793A\u6298\u53E0\u6309\u94AE",cardWidth:"\u5361\u7247\u5BBD\u5EA6",cardShadow:"\u663E\u793A\u9634\u5F71",alertTitle:"\u6807\u9898",alertType:"\u7C7B\u578B",description:"\u8F85\u52A9\u6027\u6587\u5B57",closable:"\u662F\u5426\u53EF\u5173\u95ED",closeText:"\u5173\u95ED\u6309\u94AE\u6587\u5B57",center:"\u6587\u5B57\u5C45\u4E2D",showIcon:"\u663E\u793A\u56FE\u6807",effect:"\u663E\u793A\u6548\u679C"}}};const langResources={"en-US":Se(Se(Se({something:{}},enLocale),enLocale_render),enLocale_extension),"zh-CN":Se(Se(Se({something:{}},zhLocale),zhLocale_render),zhLocale_extension)},i18n=createI18n({locale:localStorage.getItem("v_form_locale")||"zh-CN",messages:langResources}),changeLocale=function(t){i18n.setLang(t),localStorage.setItem("v_form_locale",t)},translate=function(t){return i18n.$st(t)};var i18n$1={methods:{i18nt(t){return i18n.$st(t)},i18n2t(t,d){return i18n.$st2(t,d)}}},index_vue_vue_type_style_index_0_scoped_true_lang$7="",_export_sfc$1=(t,d)=>{const e=t.__vccOpts||t;for(const[h,m]of d)e[h]=m;return e};const _sfc_main$39={name:"SvgIcon",props:{iconClass:{type:String,required:!0},className:{type:String},title:{type:String,default:""}},computed:{iconName(){return`#icon-${this.iconClass}`},svgClass(){return this.className?"svg-icon "+this.className:"svg-icon"}}},_hoisted_1$F=["xlink:href"],_hoisted_2$s={key:0};function _sfc_render$39(t,d,e,h,m,g){return require$$0$1.openBlock(),require$$0$1.createElementBlock("svg",{class:require$$0$1.normalizeClass(g.svgClass),"aria-hidden":"true"},[require$$0$1.createElementVNode("use",{"xlink:href":g.iconName},null,8,_hoisted_1$F),e.title?(require$$0$1.openBlock(),require$$0$1.createElementBlock("title",_hoisted_2$s,require$$0$1.toDisplayString(e.title),1)):require$$0$1.createCommentVNode("",!0)],2)}var SvgIcon=_export_sfc$1(_sfc_main$39,[["render",_sfc_render$39],["__scopeId","data-v-8002b89a"]]),index_vue_vue_type_style_index_0_scoped_true_lang$6="";const _sfc_main$38={name:"FieldPanel",mixins:[i18n$1],components:{SvgIcon},props:{designer:Object},inject:["getBannedWidgets","getDesignerConfig"],data(){return{designerConfig:this.getDesignerConfig(),firstTab:"componentLib",scrollerHeight:0,activeNames:["1","2","3","4"],containers:[],basicFields:[],advancedFields:[],customFields:[],formTemplates}},computed:{},created(){this.loadWidgets()},mounted(){console.log("designerdesigner",this.i18nt("designer")),this.scrollerHeight=window.innerHeight-56+"px",addWindowResizeHandler(()=>{this.$nextTick(()=>{this.scrollerHeight=window.innerHeight-56+"px"})})},methods:{isBanned(t){return this.getBannedWidgets().indexOf(t)>-1},showFormTemplates(){return this.designerConfig.formTemplates===void 0?!0:!!this.designerConfig.formTemplates},loadWidgets(){this.containers=containers.map(t=>ke(Se({key:generateId()},t),{displayName:this.i18n2t(`designer.widgetLabel.${t.type}`,`extension.widgetLabel.${t.type}`)})).filter(t=>!t.internal&&!this.isBanned(t.type)),this.basicFields=basicFields.map(t=>ke(Se({key:generateId()},t),{displayName:this.i18n2t(`designer.widgetLabel.${t.type}`,`extension.widgetLabel.${t.type}`)})).filter(t=>!this.isBanned(t.type)),this.advancedFields=advancedFields.map(t=>ke(Se({key:generateId()},t),{displayName:this.i18n2t(`designer.widgetLabel.${t.type}`,`extension.widgetLabel.${t.type}`)})).filter(t=>!this.isBanned(t.type)),this.customFields=customFields.map(t=>ke(Se({key:generateId()},t),{displayName:this.i18n2t(`designer.widgetLabel.${t.type}`,`extension.widgetLabel.${t.type}`)})).filter(t=>!this.isBanned(t.type))},handleContainerWidgetClone(t){return this.designer.copyNewContainerWidget(t)},handleFieldWidgetClone(t){return this.designer.copyNewFieldWidget(t)},checkContainerMove(t){return this.designer.checkWidgetMove(t)},checkFieldMove(t){return this.designer.checkFieldMove(t)},onContainerDragEnd(t){},addContainerByDbClick(t){this.designer.addContainerByDbClick(t)},addFieldByDbClick(t){this.designer.addFieldByDbClick(t)},loadFormTemplate(t){this.$confirm(this.i18nt("designer.hint.loadFormTemplateHint"),this.i18nt("render.hint.prompt"),{confirmButtonText:this.i18nt("render.hint.confirm"),cancelButtonText:this.i18nt("render.hint.cancel")}).then(()=>{axios.get(t).then(d=>{let e=!1;typeof d.data=="string"?e=this.designer.loadFormJson(JSON.parse(d.data)):d.data.constructor===Object&&(e=this.designer.loadFormJson(d.data)),e&&this.designer.emitHistoryChange(),this.$message.success(this.i18nt("designer.hint.loadFormTemplateSuccess"))}).catch(d=>{this.$message.error(this.i18nt("designer.hint.loadFormTemplateFailed")+":"+d)})}).catch(d=>{console.error(d)})}}},_hoisted_1$E={class:"panel-container"},_hoisted_2$r=["title","onDblclick"],_hoisted_3$m=["title","onDblclick"],_hoisted_4$f=["title","onDblclick"],_hoisted_5$d=["title","onDblclick"],_hoisted_6$c=["src"],_hoisted_7$9=["src"],_hoisted_8$6={class:"bottom clear-fix"},_hoisted_9$4={class:"ft-title"};function _sfc_render$38(t,d,e,h,m,g){const a=require$$0$1.resolveComponent("svg-icon"),u=require$$0$1.resolveComponent("draggable"),r=require$$0$1.resolveComponent("el-collapse-item"),f=require$$0$1.resolveComponent("el-collapse"),l=require$$0$1.resolveComponent("el-tab-pane"),n=require$$0$1.resolveComponent("el-popover"),i=require$$0$1.resolveComponent("el-button"),o=require$$0$1.resolveComponent("el-card"),s=require$$0$1.resolveComponent("el-tabs"),c=require$$0$1.resolveComponent("el-scrollbar");return require$$0$1.openBlock(),require$$0$1.createBlock(c,{class:"side-scroll-bar",style:require$$0$1.normalizeStyle({height:m.scrollerHeight})},{default:require$$0$1.withCtx(()=>[require$$0$1.createElementVNode("div",_hoisted_1$E,[require$$0$1.createVNode(s,{modelValue:m.firstTab,"onUpdate:modelValue":d[1]||(d[1]=p=>m.firstTab=p),class:"no-bottom-margin indent-left-margin"},{default:require$$0$1.withCtx(()=>[require$$0$1.createVNode(l,{name:"componentLib"},{label:require$$0$1.withCtx(()=>[require$$0$1.createElementVNode("span",null,[require$$0$1.createVNode(a,{"icon-class":"el-set-up"}),require$$0$1.createTextVNode(" "+require$$0$1.toDisplayString(t.i18nt("designer.componentLib")),1)])]),default:require$$0$1.withCtx(()=>[require$$0$1.createVNode(f,{modelValue:m.activeNames,"onUpdate:modelValue":d[0]||(d[0]=p=>m.activeNames=p),class:"widget-collapse"},{default:require$$0$1.withCtx(()=>[require$$0$1.createVNode(r,{name:"1",title:t.i18nt("designer.containerTitle")},{default:require$$0$1.withCtx(()=>[require$$0$1.createVNode(u,{tag:"ul",list:m.containers,"item-key":"key",group:{name:"dragGroup",pull:"clone",put:!1},clone:g.handleContainerWidgetClone,"ghost-class":"ghost",sort:!1,move:g.checkContainerMove,onEnd:g.onContainerDragEnd},{item:require$$0$1.withCtx(({element:p})=>[require$$0$1.createElementVNode("li",{class:"container-widget-item",title:p.displayName,onDblclick:$=>g.addContainerByDbClick(p)},[require$$0$1.createElementVNode("span",null,[require$$0$1.createVNode(a,{"icon-class":p.icon,"class-name":"color-svg-icon"},null,8,["icon-class"]),require$$0$1.createTextVNode(require$$0$1.toDisplayString(t.i18n2t(`designer.widgetLabel.${p.type}`,`extension.widgetLabel.${p.type}`)),1)])],40,_hoisted_2$r)]),_:1},8,["list","clone","move","onEnd"])]),_:1},8,["title"]),require$$0$1.createVNode(r,{name:"2",title:t.i18nt("designer.basicFieldTitle")},{default:require$$0$1.withCtx(()=>[require$$0$1.createVNode(u,{tag:"ul",list:m.basicFields,"item-key":"key",group:{name:"dragGroup",pull:"clone",put:!1},move:g.checkFieldMove,clone:g.handleFieldWidgetClone,"ghost-class":"ghost",sort:!1},{item:require$$0$1.withCtx(({element:p})=>[require$$0$1.createElementVNode("li",{class:"field-widget-item",title:p.displayName,onDblclick:$=>g.addFieldByDbClick(p)},[require$$0$1.createElementVNode("span",null,[require$$0$1.createVNode(a,{"icon-class":p.icon,"class-name":"color-svg-icon"},null,8,["icon-class"]),require$$0$1.createTextVNode(require$$0$1.toDisplayString(t.i18n2t(`designer.widgetLabel.${p.type}`,`extension.widgetLabel.${p.type}`)),1)])],40,_hoisted_3$m)]),_:1},8,["list","move","clone"])]),_:1},8,["title"]),require$$0$1.createVNode(r,{name:"3",title:t.i18nt("designer.advancedFieldTitle")},{default:require$$0$1.withCtx(()=>[require$$0$1.createVNode(u,{tag:"ul",list:m.advancedFields,"item-key":"key",group:{name:"dragGroup",pull:"clone",put:!1},move:g.checkFieldMove,clone:g.handleFieldWidgetClone,"ghost-class":"ghost",sort:!1},{item:require$$0$1.withCtx(({element:p})=>[require$$0$1.createElementVNode("li",{class:"field-widget-item",title:p.displayName,onDblclick:$=>g.addFieldByDbClick(p)},[require$$0$1.createElementVNode("span",null,[require$$0$1.createVNode(a,{"icon-class":p.icon,"class-name":"color-svg-icon"},null,8,["icon-class"]),require$$0$1.createTextVNode(require$$0$1.toDisplayString(t.i18n2t(`designer.widgetLabel.${p.type}`,`extension.widgetLabel.${p.type}`)),1)])],40,_hoisted_4$f)]),_:1},8,["list","move","clone"])]),_:1},8,["title"]),require$$0$1.createVNode(r,{name:"4",title:t.i18nt("designer.customFieldTitle")},{default:require$$0$1.withCtx(()=>[require$$0$1.createVNode(u,{tag:"ul",list:m.customFields,"item-key":"key",group:{name:"dragGroup",pull:"clone",put:!1},move:g.checkFieldMove,clone:g.handleFieldWidgetClone,"ghost-class":"ghost",sort:!1},{item:require$$0$1.withCtx(({element:p})=>[require$$0$1.createElementVNode("li",{class:"field-widget-item",title:p.displayName,onDblclick:$=>g.addFieldByDbClick(p)},[require$$0$1.createElementVNode("span",null,[require$$0$1.createVNode(a,{"icon-class":p.icon,"class-name":"color-svg-icon"},null,8,["icon-class"]),require$$0$1.createTextVNode(require$$0$1.toDisplayString(t.i18n2t(`designer.widgetLabel.${p.type}`,`extension.widgetLabel.${p.type}`)),1)])],40,_hoisted_5$d)]),_:1},8,["list","move","clone"])]),_:1},8,["title"])]),_:1},8,["modelValue"])]),_:1}),g.showFormTemplates()?(require$$0$1.openBlock(),require$$0$1.createBlock(l,{key:0,name:"formLib",style:{padding:"8px"}},{label:require$$0$1.withCtx(()=>[require$$0$1.createElementVNode("span",null,[require$$0$1.createVNode(a,{"icon-class":"el-form-template"}),require$$0$1.createTextVNode(" "+require$$0$1.toDisplayString(t.i18nt("designer.formLib")),1)])]),default:require$$0$1.withCtx(()=>[(require$$0$1.openBlock(!0),require$$0$1.createElementBlock(require$$0$1.Fragment,null,require$$0$1.renderList(m.formTemplates,(p,$)=>(require$$0$1.openBlock(),require$$0$1.createBlock(o,{"bord-style":{padding:"0"},shadow:"hover",class:"ft-card"},{default:require$$0$1.withCtx(()=>[require$$0$1.createVNode(n,{placement:"right",trigger:"hover"},{reference:require$$0$1.withCtx(()=>[require$$0$1.createElementVNode("img",{src:p.imgUrl,style:{width:"200px"}},null,8,_hoisted_6$c)]),default:require$$0$1.withCtx(()=>[require$$0$1.createElementVNode("img",{src:p.imgUrl,style:{height:"600px",width:"720px"}},null,8,_hoisted_7$9)]),_:2},1024),require$$0$1.createElementVNode("div",_hoisted_8$6,[require$$0$1.createElementVNode("span",_hoisted_9$4,"#"+require$$0$1.toDisplayString($+1)+" "+require$$0$1.toDisplayString(p.title),1),require$$0$1.createVNode(i,{link:"",type:"primary",class:"right-button",onClick:v=>g.loadFormTemplate(p.jsonUrl)},{default:require$$0$1.withCtx(()=>[require$$0$1.createTextVNode(require$$0$1.toDisplayString(t.i18nt("designer.hint.loadFormTemplate")),1)]),_:2},1032,["onClick"])])]),_:2},1024))),256))]),_:1})):require$$0$1.createCommentVNode("",!0)]),_:1},8,["modelValue"])])]),_:1},8,["style"])}var WidgetPanel=_export_sfc$1(_sfc_main$38,[["render",_sfc_render$38],["__scopeId","data-v-335b6326"]]),emitter={data(){return{vfEvents:{}}},methods:{emit$(t,d){this.vfEvents[t]&&this.vfEvents[t].forEach(e=>{e(d)})},on$(t,d){this.vfEvents[t]=this.vfEvents[t]||[],this.vfEvents[t].push(d)},off$(t,d){if(this.vfEvents[t]){if(d==null){this.vfEvents[t].length=0;return}for(let e=0;e{if(this.widgetRefList[m].$options.componentName===d){let a=this.widgetRefList[m];a.emit$.call(a,e,h)}}),this.refList&&Object.keys(this.refList).forEach(m=>{if(this.refList[m].$options.componentName===d){let a=this.refList[m];a.emit$.call(a,e,h)}})}}};const _sfc_main$37={name:"container-item-wrapper",props:{widget:Object},computed:{customClass(){return this.widget.options.customClass?this.widget.options.customClass.join(" "):""}}};function _sfc_render$37(t,d,e,h,m,g){return require$$0$1.openBlock(),require$$0$1.createElementBlock("div",{class:require$$0$1.normalizeClass(["container-wrapper",[g.customClass]])},[require$$0$1.renderSlot(t.$slots,"default")],2)}var ContainerItemWrapper=_export_sfc$1(_sfc_main$37,[["render",_sfc_render$37]]),__glob_0_0$3=Object.freeze(Object.defineProperty({__proto__:null,default:ContainerItemWrapper},Symbol.toStringTag,{value:"Module"})),refMixin={methods:{initRefList(){this.refList!==null&&!!this.widget.options.name&&(this.refList[this.widget.options.name]=this)},getWidgetRef(t,d){let e=this.refList[t];return!e&&!!d&&this.$message.error(this.i18nt("render.hint.refNotFound")+t),e},getFormRef(){return this.refList.v_form_ref},getComponentByContainer(t){return t.type==="grid"?"vf-grid-item":t.type+"-item"}}},staticContentWrapper_vue_vue_type_style_index_0_scoped_true_lang="";const _sfc_main$36={name:"static-content-wrapper",mixins:[i18n$1],components:{SvgIcon},props:{field:Object,designer:Object,parentWidget:Object,parentList:Array,indexOfParentList:Number,designState:{type:Boolean,default:!1},displayStyle:{type:String,default:"block"},subFormRowIndex:{type:Number,default:-1},subFormColIndex:{type:Number,default:-1},subFormRowId:{type:String,default:""}},computed:{selected(){return!!this.designer&&this.field.id===this.designer.selectedId},customClass(){return this.field.options.customClass?this.field.options.customClass.join(" "):""}},methods:{selectField(t){this.designer&&(this.designer.setSelected(t),this.designer.emitEvent("field-selected",this.parentWidget))},selectParentWidget(){this.parentWidget?this.designer.setSelected(this.parentWidget):this.designer.clearSelected()},moveUpWidget(){this.designer.moveUpWidget(this.parentList,this.indexOfParentList),this.designer.emitHistoryChange()},moveDownWidget(){this.designer.moveDownWidget(this.parentList,this.indexOfParentList),this.designer.emitHistoryChange()},removeFieldWidget(){if(this.parentList){const t=this.designer.selectedWidgetName;let d=null;this.parentList.length===1?this.parentWidget&&(d=this.parentWidget):this.parentList.length===1+this.indexOfParentList?d=this.parentList[this.indexOfParentList-1]:d=this.parentList[this.indexOfParentList+1],this.$nextTick(()=>{this.parentList.splice(this.indexOfParentList,1),this.designer.setSelected(d),this.designer.formWidget.deleteWidgetRef(t),this.designer.emitHistoryChange()})}}}},_hoisted_1$D={key:0,class:"field-action"},_hoisted_2$q=["title"],_hoisted_3$l=["title"],_hoisted_4$e=["title"],_hoisted_5$c=["title"],_hoisted_6$b={key:1,class:"drag-handler background-opacity"},_hoisted_7$8=["title"],_hoisted_8$5={key:0};function _sfc_render$36(t,d,e,h,m,g){const a=require$$0$1.resolveComponent("svg-icon");return require$$0$1.openBlock(),require$$0$1.createElementBlock("div",{class:require$$0$1.normalizeClass(["field-wrapper",{"design-time-bottom-margin":!!this.designer}]),style:require$$0$1.normalizeStyle({display:e.displayStyle})},[!e.field.options.hidden||e.designState===!0?(require$$0$1.openBlock(),require$$0$1.createElementBlock("div",{key:0,class:require$$0$1.normalizeClass(["static-content-item",[g.selected?"selected":"",g.customClass]]),style:require$$0$1.normalizeStyle({display:e.displayStyle}),onClick:d[0]||(d[0]=require$$0$1.withModifiers(u=>g.selectField(e.field),["stop"]))},[require$$0$1.renderSlot(t.$slots,"default",{},void 0,!0)],6)):require$$0$1.createCommentVNode("",!0),this.designer?(require$$0$1.openBlock(),require$$0$1.createElementBlock(require$$0$1.Fragment,{key:1},[e.designer.selectedId===e.field.id?(require$$0$1.openBlock(),require$$0$1.createElementBlock("div",_hoisted_1$D,[require$$0$1.createElementVNode("i",{title:t.i18nt("designer.hint.selectParentWidget"),onClick:d[1]||(d[1]=require$$0$1.withModifiers(u=>g.selectParentWidget(e.field),["stop"]))},[require$$0$1.createVNode(a,{"icon-class":"el-back"})],8,_hoisted_2$q),!!e.parentList&&e.parentList.length>1?(require$$0$1.openBlock(),require$$0$1.createElementBlock("i",{key:0,title:t.i18nt("designer.hint.moveUpWidget"),onClick:d[2]||(d[2]=require$$0$1.withModifiers(u=>g.moveUpWidget(e.field),["stop"]))},[require$$0$1.createVNode(a,{"icon-class":"el-move-up"})],8,_hoisted_3$l)):require$$0$1.createCommentVNode("",!0),!!e.parentList&&e.parentList.length>1?(require$$0$1.openBlock(),require$$0$1.createElementBlock("i",{key:1,title:t.i18nt("designer.hint.moveDownWidget"),onClick:d[3]||(d[3]=require$$0$1.withModifiers(u=>g.moveDownWidget(e.field),["stop"]))},[require$$0$1.createVNode(a,{"icon-class":"el-move-down"})],8,_hoisted_4$e)):require$$0$1.createCommentVNode("",!0),require$$0$1.createElementVNode("i",{title:t.i18nt("designer.hint.remove"),onClick:d[4]||(d[4]=require$$0$1.withModifiers((...u)=>g.removeFieldWidget&&g.removeFieldWidget(...u),["stop"]))},[require$$0$1.createVNode(a,{"icon-class":"el-delete"})],8,_hoisted_5$c)])):require$$0$1.createCommentVNode("",!0),e.designer.selectedId===e.field.id?(require$$0$1.openBlock(),require$$0$1.createElementBlock("div",_hoisted_6$b,[require$$0$1.createElementVNode("i",{title:t.i18nt("designer.hint.dragHandler")},[require$$0$1.createVNode(a,{"icon-class":"el-drag-move"})],8,_hoisted_7$8),require$$0$1.createElementVNode("i",null,require$$0$1.toDisplayString(t.i18n2t(`designer.widgetLabel.${e.field.type}`,`extension.widgetLabel.${e.field.type}`)),1),e.field.options.hidden===!0?(require$$0$1.openBlock(),require$$0$1.createElementBlock("i",_hoisted_8$5,[require$$0$1.createVNode(a,{"icon-class":"el-hide"})])):require$$0$1.createCommentVNode("",!0)])):require$$0$1.createCommentVNode("",!0)],64)):require$$0$1.createCommentVNode("",!0)],6)}var StaticContentWrapper=_export_sfc$1(_sfc_main$36,[["render",_sfc_render$36],["__scopeId","data-v-41799baa"]]),__glob_0_19$1=Object.freeze(Object.defineProperty({__proto__:null,default:StaticContentWrapper},Symbol.toStringTag,{value:"Module"}));const getRegExp=function(t){return{number:"/^[-]?\\d+(\\.\\d+)?$/",letter:"/^[A-Za-z]+$/",letterAndNumber:"/^[A-Za-z0-9]+$/",mobilePhone:"/^[1][3-9][0-9]{9}$/",letterStartNumberIncluded:"/^[A-Za-z]+[A-Za-z\\d]*$/",noChinese:"/^[^\u4E00-\u9FA5]+$/",chinese:"/^[\u4E00-\u9FA5]+$/",email:"/^([-_A-Za-z0-9.]+)@([_A-Za-z0-9]+\\.)+[A-Za-z0-9]{2,3}$/",url:"/^([hH][tT]{2}[pP]:\\/\\/|[hH][tT]{2}[pP][sS]:\\/\\/)(([A-Za-z0-9-~]+)\\.)+([A-Za-z0-9-~\\/])+$/"}[t]},validateFn=function(validatorName,rule,value,callback,defaultErrorMsg){if(isNull(value)||value.length<=0){callback();return}const reg=eval(getRegExp(validatorName));if(reg.test(value))callback();else{let t=rule.errorMsg||defaultErrorMsg;callback(new Error(t))}},FormValidators={number(t,d,e){validateFn("number",t,d,e,"["+t.label+"]\u5305\u542B\u975E\u6570\u5B57\u5B57\u7B26")},letter(t,d,e){validateFn("letter",t,d,e,"["+t.label+"]\u5305\u542B\u975E\u5B57\u6BCD\u5B57\u7B26")},letterAndNumber(t,d,e){validateFn("letterAndNumber",t,d,e,"["+t.label+"]\u53EA\u80FD\u8F93\u5165\u5B57\u6BCD\u6216\u6570\u5B57")},mobilePhone(t,d,e){validateFn("mobilePhone",t,d,e,"["+t.label+"]\u624B\u673A\u53F7\u7801\u683C\u5F0F\u6709\u8BEF")},noBlankStart(t,d,e){},noBlankEnd(t,d,e){},letterStartNumberIncluded(t,d,e){validateFn("letterStartNumberIncluded",t,d,e,"["+t.label+"]\u5FC5\u987B\u4EE5\u5B57\u6BCD\u5F00\u5934\uFF0C\u53EF\u5305\u542B\u6570\u5B57")},noChinese(t,d,e){validateFn("noChinese",t,d,e,"["+t.label+"]\u4E0D\u53EF\u8F93\u5165\u4E2D\u6587\u5B57\u7B26")},chinese(t,d,e){validateFn("chinese",t,d,e,"["+t.label+"]\u53EA\u80FD\u8F93\u5165\u4E2D\u6587\u5B57\u7B26")},email(t,d,e){validateFn("email",t,d,e,"["+t.label+"]\u90AE\u7BB1\u683C\u5F0F\u6709\u8BEF")},url(t,d,e){validateFn("url",t,d,e,"["+t.label+"]URL\u683C\u5F0F\u6709\u8BEF")},regExp(rule,value,callback){if(isNull(value)||value.length<=0){callback();return}const pattern=eval(rule.regExp);if(pattern.test(value))callback();else{let t=rule.errorMsg||"["+rule.label+"]invalid value";callback(new Error(t))}}};function mitt(t){return{all:t=t||new Map,on:function(d,e){var h=t.get(d);h?h.push(e):t.set(d,[e])},off:function(d,e){var h=t.get(d);h&&(e?h.splice(h.indexOf(e)>>>0,1):t.set(d,[]))},emit:function(d,e){var h=t.get(d);h&&h.slice().map(function(m){m(e)}),(h=t.get("*"))&&h.slice().map(function(m){m(d,e)})}}}const instance=mitt(),eventBus={};eventBus.$on=instance.on,eventBus.$off=instance.off,eventBus.$emit=instance.emit;var fieldMixin={inject:["refList","getFormConfig","getGlobalDsv","globalOptionData","globalModel","getOptionData"],computed:{formConfig(){return this.getFormConfig()},widgetSize(){return this.field.options.size||"default"},subFormName(){return this.parentWidget?this.parentWidget.options.name:""},subFormItemFlag(){return this.parentWidget?this.parentWidget.type==="sub-form":!1},formModel:{cache:!1,get(){return this.globalModel.formModel}}},methods:{getPropName(){return this.subFormItemFlag&&!this.designState?this.subFormName+"."+this.subFormRowIndex+"."+this.field.options.name+"":this.field.options.name},initFieldModel(){if(!!this.field.formItemFlag){if(!!this.subFormItemFlag&&!this.designState){let t=this.formModel[this.subFormName];(t===void 0||t[this.subFormRowIndex]===void 0||t[this.subFormRowIndex][this.field.options.name]===void 0)&&this.field.options.defaultValue!==void 0?(this.fieldModel=this.field.options.defaultValue,t[this.subFormRowIndex][this.field.options.name]=this.field.options.defaultValue):t[this.subFormRowIndex][this.field.options.name]===void 0?(this.fieldModel=null,t[this.subFormRowIndex][this.field.options.name]=null):this.fieldModel=t[this.subFormRowIndex][this.field.options.name],setTimeout(()=>{this.handleOnChangeForSubForm(this.fieldModel,this.oldFieldValue,t,this.subFormRowId)},800),this.oldFieldValue=deepClone(this.fieldModel),this.initFileList();return}this.formModel[this.field.options.name]===void 0&&this.field.options.defaultValue!==void 0?this.fieldModel=this.field.options.defaultValue:this.formModel[this.field.options.name]===void 0?this.formModel[this.field.options.name]=null:this.fieldModel=this.formModel[this.field.options.name],this.oldFieldValue=deepClone(this.fieldModel),this.initFileList()}},initFileList(){this.field.type!=="picture-upload"&&this.field.type!=="file-upload"||this.designState===!0||this.fieldModel&&(Array.isArray(this.fieldModel)?this.fileList=deepClone(this.fieldModel):this.fileList.splice(0,0,deepClone(this.fieldModel)))},initEventHandler(){this.on$("setFormData",t=>{console.log("formModel of globalModel----------",this.globalModel.formModel),this.subFormItemFlag||this.setValue(t[this.field.options.name])}),this.on$("field-value-changed",t=>{if(this.subFormItemFlag){let d=this.formModel[this.subFormName];this.handleOnChangeForSubForm(t[0],t[1],d,this.subFormRowId)}else this.handleOnChange(t[0],t[1])}),this.on$("reloadOptionItems",t=>{(t.length===0||t.indexOf(this.field.options.name)>-1)&&this.initOptionItems(!0)})},handleOnCreated(){this.field.options.onCreated&&new Function(this.field.options.onCreated).call(this)},handleOnMounted(){this.field.options.onMounted&&new Function(this.field.options.onMounted).call(this)},registerToRefList(t){this.refList!==null&&!!this.field.options.name&&(this.subFormItemFlag&&!this.designState?(t&&delete this.refList[t+"@row"+this.subFormRowId],this.refList[this.field.options.name+"@row"+this.subFormRowId]=this):(t&&delete this.refList[t],this.refList[this.field.options.name]=this))},unregisterFromRefList(){if(this.refList!==null&&!!this.field.options.name){let t=this.field.options.name;this.subFormItemFlag&&!this.designState?delete this.refList[t+"@row"+this.subFormRowId]:delete this.refList[t]}},initOptionItems(t){if(!this.designState&&(this.field.type==="radio"||this.field.type==="checkbox"||this.field.type==="select"||this.field.type==="cascader")){const d=this.getOptionData();!!d&&d.hasOwnProperty(this.field.options.name)&&(t?this.reloadOptions(d[this.field.options.name]):this.loadOptions(d[this.field.options.name]))}},refreshDefaultValue(){this.designState===!0&&this.field.options.defaultValue!==void 0&&(this.fieldModel=this.field.options.defaultValue)},clearFieldRules(){!this.field.formItemFlag||this.rules.splice(0,this.rules.length)},buildFieldRules(){if(!(!this.field.formItemFlag&&this.field.options.hidden)){if(this.rules.splice(0,this.rules.length),this.field.options.required&&this.rules.push({required:!0,trigger:["blur"],message:this.field.options.requiredHint||this.i18nt("render.hint.fieldRequired")}),this.field.options.validation){let t=this.field.options.validation;FormValidators[t]?this.rules.push({validator:FormValidators[t],trigger:["blur","change"],label:this.field.options.label,errorMsg:this.field.options.validationHint}):this.rules.push({validator:FormValidators.regExp,trigger:["blur","change"],regExp:t,label:this.field.options.label,errorMsg:this.field.options.validationHint})}if(this.field.options.onValidate){let t=(d,e,h)=>new Function("rule","value","callback",this.field.options.onValidate).call(this,d,e,h);this.rules.push({validator:t,trigger:["blur","change"],label:this.field.options.label})}}},disableChangeValidate(){!this.rules||this.rules.forEach(t=>{t.trigger&&t.trigger.splice(0,t.trigger.length)})},enableChangeValidate(){!this.rules||this.rules.forEach(t=>{t.trigger&&(t.trigger.push("blur"),t.trigger.push("change"))})},disableOptionOfList(t,d){!!t&&t.length>0&&t.forEach(e=>{e.value===d&&(e.disabled=!0)})},enableOptionOfList(t,d){!!t&&t.length>0&&t.forEach(e=>{e.value===d&&(e.disabled=!1)})},emitFieldDataChange(t,d){this.emit$("field-value-changed",[t,d]),this.dispatch("VFormRender","fieldChange",[this.field.options.name,t,d,this.subFormName,this.subFormRowIndex])},syncUpdateFormModel(t){if(!this.designState)if(this.subFormItemFlag){let e=(this.formModel[this.subFormName]||[{}])[this.subFormRowIndex];e&&(e[this.field.options.name]=t)}else this.formModel[this.field.options.name]=t},handleChangeEvent(t){this.syncUpdateFormModel(t),this.emitFieldDataChange(t,this.oldFieldValue),this.oldFieldValue=deepClone(t),this.dispatch("VFormRender","fieldValidation",[this.getPropName()])},handleFocusCustomEvent(t){this.oldFieldValue=deepClone(this.fieldModel),this.field.options.onFocus&&new Function("event",this.field.options.onFocus).call(this,t)},handleBlurCustomEvent(t){this.field.options.onBlur&&new Function("event",this.field.options.onBlur).call(this,t)},handleInputCustomEvent(t){this.syncUpdateFormModel(t),this.dispatch("VFormRender","fieldValidation",[this.getPropName()]),this.field.options.onInput&&new Function("value",this.field.options.onInput).call(this,t)},emitAppendButtonClick(){this.designState||(this.field.options.onAppendButtonClick?new Function(this.field.options.onAppendButtonClick).call(this):this.dispatch("VFormRender","appendButtonClick",[this]))},handleOnChange(t,d){this.field.options.onChange&&new Function("value","oldValue",this.field.options.onChange).call(this,t,d)},handleOnChangeForSubForm(t,d,e,h){this.field.options.onChange&&new Function("value","oldValue","subFormData","rowId",this.field.options.onChange).call(this,t,d,e,h)},handleButtonWidgetClick(){this.designState||(this.field.options.onClick?new Function(this.field.options.onClick).call(this):this.dispatch("VFormRender","buttonClick",[this]))},remoteQuery(t){this.field.options.onRemoteQuery&&new Function("keyword",this.field.options.onRemoteQuery).call(this,t)},getFormRef(){return this.refList.v_form_ref},getWidgetRef(t,d){let e=this.refList[t];return!e&&!!d&&this.$message.error(this.i18nt("render.hint.refNotFound")+t),e},getFieldEditor(){return this.$refs.fieldEditor},setValue(t){if(this.field.formItemFlag){let d=deepClone(this.fieldModel);this.fieldModel=t,this.initFileList(),this.syncUpdateFormModel(t),this.emitFieldDataChange(t,d)}},getValue(){return this.fieldModel},resetField(){let t=this.field.options.defaultValue;this.setValue(t),this.$nextTick(()=>{}),(this.field.type==="picture-upload"||this.field.type==="file-upload")&&(this.$refs.fieldEditor.clearFiles(),this.fileList.splice(0,this.fileList.length))},setWidgetOption(t,d){this.field.options.hasOwnProperty(t)&&(this.field.options[t]=d)},setReadonly(t){this.field.options.readonly=t},setDisabled(t){this.field.options.disabled=t},setAppendButtonVisible(t){this.field.options.appendButton=t},setAppendButtonDisabled(t){this.field.options.appendButtonDisabled=t},setHidden(t){this.field.options.hidden=t,t?this.clearFieldRules():this.buildFieldRules()},setRequired(t){this.field.options.required=t,this.buildFieldRules()},setLabel(t){this.field.options.label=t},focus(){!!this.getFieldEditor()&&!!this.getFieldEditor().focus&&this.getFieldEditor().focus()},clearSelectedOptions(){this.field.type!=="checkbox"&&this.field.type!=="radio"&&this.field.type!=="select"||(this.field.type==="checkbox"||this.field.type==="select"&&this.field.options.multiple?this.fieldModel=[]:this.fieldModel="")},loadOptions(t){this.field.options.optionItems=deepClone(t)},reloadOptions(t){this.field.options.optionItems=deepClone(t)},disableOption(t){this.disableOptionOfList(this.field.options.optionItems,t)},enableOption(t){this.enableOptionOfList(this.field.options.optionItems,t)},getOptionItems(){return this.field.options.optionItems},setUploadHeader(t,d){this.uploadHeaders[t]=d},setUploadData(t,d){this.uploadData[t]=d},setToolbar(t){this.customToolbar=t},isSubFormItem(){return this.parentWidget?this.parentWidget.type==="sub-form":!1},addCssClass(t){this.field.options.customClass?this.field.options.customClass.push(t):this.field.options.customClass=[t]},removeCssClass(t){if(!this.field.options.customClass)return;let d=-1;this.field.options.customClass.map((e,h)=>{e===t&&(d=h)}),d>-1&&this.field.options.customClass.splice(d,1)}}},buttonWidget_vue_vue_type_style_index_0_scoped_true_lang="";const _sfc_main$35={name:"button-widget",componentName:"FieldWidget",mixins:[emitter,fieldMixin,i18n$1],props:{field:Object,parentWidget:Object,parentList:Array,indexOfParentList:Number,designer:Object,designState:{type:Boolean,default:!1},subFormRowIndex:{type:Number,default:-1},subFormColIndex:{type:Number,default:-1},subFormRowId:{type:String,default:""}},components:{StaticContentWrapper},computed:{},beforeCreate(){},created(){this.registerToRefList(),this.initEventHandler(),this.handleOnCreated()},mounted(){this.handleOnMounted()},beforeUnmount(){this.unregisterFromRefList()},methods:{}};function _sfc_render$35(t,d,e,h,m,g){const a=require$$0$1.resolveComponent("el-button"),u=require$$0$1.resolveComponent("static-content-wrapper");return require$$0$1.openBlock(),require$$0$1.createBlock(u,{designer:e.designer,field:e.field,"design-state":e.designState,"display-style":e.field.options.displayStyle,"parent-widget":e.parentWidget,"parent-list":e.parentList,"index-of-parent-list":e.indexOfParentList,"sub-form-row-index":e.subFormRowIndex,"sub-form-col-index":e.subFormColIndex,"sub-form-row-id":e.subFormRowId},{default:require$$0$1.withCtx(()=>[require$$0$1.createVNode(a,{ref:"fieldEditor",type:e.field.options.type,size:t.widgetSize,plain:e.field.options.plain,round:e.field.options.round,circle:e.field.options.circle,icon:e.field.options.icon,disabled:e.field.options.disabled,onClick:t.handleButtonWidgetClick},{default:require$$0$1.withCtx(()=>[require$$0$1.createTextVNode(require$$0$1.toDisplayString(e.field.options.label),1)]),_:1},8,["type","size","plain","round","circle","icon","disabled","onClick"])]),_:1},8,["designer","field","design-state","display-style","parent-widget","parent-list","index-of-parent-list","sub-form-row-index","sub-form-col-index","sub-form-row-id"])}var buttonWidget=_export_sfc$1(_sfc_main$35,[["render",_sfc_render$35],["__scopeId","data-v-1ba2a127"]]),__glob_0_0$2=Object.freeze(Object.defineProperty({__proto__:null,default:buttonWidget},Symbol.toStringTag,{value:"Module"})),formItemWrapper_vue_vue_type_style_index_0_scoped_true_lang="";const _sfc_main$34={name:"form-item-wrapper",mixins:[i18n$1],components:{SvgIcon},props:{field:Object,designer:Object,parentWidget:Object,parentList:Array,indexOfParentList:Number,designState:{type:Boolean,default:!1},subFormRowIndex:{type:Number,default:-1},subFormColIndex:{type:Number,default:-1},subFormRowId:{type:String,default:""},rules:Array},inject:["getFormConfig"],computed:{formConfig(){return this.getFormConfig()},selected(){return!!this.designer&&this.field.id===this.designer.selectedId},label(){return this.field.options.labelHidden?"":this.field.options.label},labelWidth(){return this.field.options.labelHidden?0:this.field.options.labelWidth?this.field.options.labelWidth:this.designer?this.designer.formConfig.labelWidth:this.formConfig.labelWidth},labelAlign(){return this.field.options.labelAlign?this.field.options.labelAlign:this.designer?this.designer.formConfig.labelAlign||"label-left-align":this.formConfig.labelAlign||"label-left-align"},customClass(){return this.field.options.customClass?this.field.options.customClass.join(" "):""},subFormName(){return this.parentWidget?this.parentWidget.options.name:""},subFormItemFlag(){return this.parentWidget?this.parentWidget.type==="sub-form":!1}},created(){},methods:{selectField(t){this.designer&&(this.designer.setSelected(t),this.designer.emitEvent("field-selected",this.parentWidget))},selectParentWidget(){this.parentWidget?this.designer.setSelected(this.parentWidget):this.designer.clearSelected()},moveUpWidget(){this.designer.moveUpWidget(this.parentList,this.indexOfParentList),this.designer.emitHistoryChange()},moveDownWidget(){this.designer.moveDownWidget(this.parentList,this.indexOfParentList),this.designer.emitHistoryChange()},removeFieldWidget(){if(this.parentList){const t=this.designer.selectedWidgetName;let d=null;this.parentList.length===1?this.parentWidget&&(d=this.parentWidget):this.parentList.length===1+this.indexOfParentList?d=this.parentList[this.indexOfParentList-1]:d=this.parentList[this.indexOfParentList+1],this.$nextTick(()=>{this.parentList.splice(this.indexOfParentList,1),this.designer.setSelected(d),this.designer.formWidget.deleteWidgetRef(t),this.designer.emitHistoryChange()})}},getPropName(){return this.subFormItemFlag&&!this.designState?this.subFormName+"."+this.subFormRowIndex+"."+this.field.options.name+"":this.field.options.name}}},_hoisted_1$C={key:0,class:"custom-label"},_hoisted_2$p={key:0,class:"field-action"},_hoisted_3$k=["title"],_hoisted_4$d=["title"],_hoisted_5$b=["title"],_hoisted_6$a=["title"],_hoisted_7$7={key:1,class:"drag-handler background-opacity"},_hoisted_8$4=["title"],_hoisted_9$3={key:0};function _sfc_render$34(t,d,e,h,m,g){const a=require$$0$1.resolveComponent("svg-icon"),u=require$$0$1.resolveComponent("el-tooltip"),r=require$$0$1.resolveComponent("el-form-item");return require$$0$1.openBlock(),require$$0$1.createElementBlock("div",{class:require$$0$1.normalizeClass(["field-wrapper",{"design-time-bottom-margin":!!this.designer}])},[!!e.field.formItemFlag&&(!e.field.options.hidden||e.designState===!0)?(require$$0$1.openBlock(),require$$0$1.createBlock(r,{key:0,label:g.label,"label-width":g.labelWidth+"px",title:e.field.options.labelTooltip,rules:e.rules,prop:g.getPropName(),class:require$$0$1.normalizeClass([g.selected?"selected":"",g.labelAlign,g.customClass,e.field.options.required?"required":""]),onClick:d[0]||(d[0]=require$$0$1.withModifiers(f=>g.selectField(e.field),["stop"]))},{label:require$$0$1.withCtx(()=>[e.field.options.labelIconClass?(require$$0$1.openBlock(),require$$0$1.createElementBlock("span",_hoisted_1$C,[e.field.options.labelIconPosition==="front"?(require$$0$1.openBlock(),require$$0$1.createElementBlock(require$$0$1.Fragment,{key:0},[e.field.options.labelTooltip?(require$$0$1.openBlock(),require$$0$1.createElementBlock(require$$0$1.Fragment,{key:0},[require$$0$1.createVNode(u,{content:e.field.options.labelTooltip,effect:"light"},{default:require$$0$1.withCtx(()=>[require$$0$1.createVNode(a,{"icon-class":e.field.options.labelIconClass},null,8,["icon-class"])]),_:1},8,["content"]),require$$0$1.createTextVNode(require$$0$1.toDisplayString(g.label),1)],64)):(require$$0$1.openBlock(),require$$0$1.createElementBlock(require$$0$1.Fragment,{key:1},[require$$0$1.createVNode(a,{"icon-class":e.field.options.labelIconClass},null,8,["icon-class"]),require$$0$1.createTextVNode(require$$0$1.toDisplayString(g.label),1)],64))],64)):e.field.options.labelIconPosition==="rear"?(require$$0$1.openBlock(),require$$0$1.createElementBlock(require$$0$1.Fragment,{key:1},[e.field.options.labelTooltip?(require$$0$1.openBlock(),require$$0$1.createElementBlock(require$$0$1.Fragment,{key:0},[require$$0$1.createTextVNode(require$$0$1.toDisplayString(g.label),1),require$$0$1.createVNode(u,{content:e.field.options.labelTooltip,effect:"light"},{default:require$$0$1.withCtx(()=>[require$$0$1.createVNode(a,{"icon-class":e.field.options.labelIconClass},null,8,["icon-class"])]),_:1},8,["content"])],64)):(require$$0$1.openBlock(),require$$0$1.createElementBlock(require$$0$1.Fragment,{key:1},[require$$0$1.createTextVNode(require$$0$1.toDisplayString(g.label),1),require$$0$1.createVNode(a,{"icon-class":e.field.options.labelIconClass},null,8,["icon-class"])],64))],64)):require$$0$1.createCommentVNode("",!0)])):require$$0$1.createCommentVNode("",!0)]),default:require$$0$1.withCtx(()=>[require$$0$1.renderSlot(t.$slots,"default",{},void 0,!0)]),_:3},8,["label","label-width","title","rules","prop","class"])):require$$0$1.createCommentVNode("",!0),this.designer?(require$$0$1.openBlock(),require$$0$1.createElementBlock(require$$0$1.Fragment,{key:1},[e.designer.selectedId===e.field.id?(require$$0$1.openBlock(),require$$0$1.createElementBlock("div",_hoisted_2$p,[require$$0$1.createElementVNode("i",{title:t.i18nt("designer.hint.selectParentWidget"),onClick:d[1]||(d[1]=require$$0$1.withModifiers(f=>g.selectParentWidget(e.field),["stop"]))},[require$$0$1.createVNode(a,{"icon-class":"el-back"})],8,_hoisted_3$k),!!e.parentList&&e.parentList.length>1?(require$$0$1.openBlock(),require$$0$1.createElementBlock("i",{key:0,title:t.i18nt("designer.hint.moveUpWidget"),onClick:d[2]||(d[2]=require$$0$1.withModifiers(f=>g.moveUpWidget(e.field),["stop"]))},[require$$0$1.createVNode(a,{"icon-class":"el-move-up"})],8,_hoisted_4$d)):require$$0$1.createCommentVNode("",!0),!!e.parentList&&e.parentList.length>1?(require$$0$1.openBlock(),require$$0$1.createElementBlock("i",{key:1,title:t.i18nt("designer.hint.moveDownWidget"),onClick:d[3]||(d[3]=require$$0$1.withModifiers(f=>g.moveDownWidget(e.field),["stop"]))},[require$$0$1.createVNode(a,{"icon-class":"el-move-down"})],8,_hoisted_5$b)):require$$0$1.createCommentVNode("",!0),require$$0$1.createElementVNode("i",{title:t.i18nt("designer.hint.remove"),onClick:d[4]||(d[4]=require$$0$1.withModifiers((...f)=>g.removeFieldWidget&&g.removeFieldWidget(...f),["stop"]))},[require$$0$1.createVNode(a,{"icon-class":"el-delete"})],8,_hoisted_6$a)])):require$$0$1.createCommentVNode("",!0),e.designer.selectedId===e.field.id?(require$$0$1.openBlock(),require$$0$1.createElementBlock("div",_hoisted_7$7,[require$$0$1.createElementVNode("i",{title:t.i18nt("designer.hint.dragHandler")},[require$$0$1.createVNode(a,{"icon-class":"el-drag-move"})],8,_hoisted_8$4),require$$0$1.createElementVNode("i",null,require$$0$1.toDisplayString(t.i18n2t(`designer.widgetLabel.${e.field.type}`,`extension.widgetLabel.${e.field.type}`)),1),e.field.options.hidden===!0?(require$$0$1.openBlock(),require$$0$1.createElementBlock("i",_hoisted_9$3,[require$$0$1.createVNode(a,{"icon-class":"el-hide"})])):require$$0$1.createCommentVNode("",!0)])):require$$0$1.createCommentVNode("",!0)],64)):require$$0$1.createCommentVNode("",!0)],2)}var FormItemWrapper=_export_sfc$1(_sfc_main$34,[["render",_sfc_render$34],["__scopeId","data-v-150e0c61"]]),__glob_0_8$1=Object.freeze(Object.defineProperty({__proto__:null,default:FormItemWrapper},Symbol.toStringTag,{value:"Module"})),cascaderWidget_vue_vue_type_style_index_0_scoped_true_lang="";const _sfc_main$33={name:"cascader-widget",componentName:"FieldWidget",mixins:[emitter,fieldMixin,i18n$1],props:{field:Object,parentWidget:Object,parentList:Array,indexOfParentList:Number,designer:Object,designState:{type:Boolean,default:!1},subFormRowIndex:{type:Number,default:-1},subFormColIndex:{type:Number,default:-1},subFormRowId:{type:String,default:""}},components:{FormItemWrapper},data(){return{oldFieldValue:null,fieldModel:null,rules:[]}},computed:{showFullPath(){return this.field.options.showAllLevels===void 0||!!this.field.options.showAllLevels}},beforeCreate(){},created(){this.initOptionItems(),this.initFieldModel(),this.registerToRefList(),this.initEventHandler(),this.buildFieldRules(),this.handleOnCreated()},mounted(){this.handleOnMounted()},beforeUnmount(){this.unregisterFromRefList()},methods:{}},_hoisted_1$B={class:"full-width-input"};function _sfc_render$33(t,d,e,h,m,g){const a=require$$0$1.resolveComponent("el-cascader"),u=require$$0$1.resolveComponent("form-item-wrapper");return require$$0$1.openBlock(),require$$0$1.createBlock(u,{designer:e.designer,field:e.field,rules:m.rules,"design-state":e.designState,"parent-widget":e.parentWidget,"parent-list":e.parentList,"index-of-parent-list":e.indexOfParentList,"sub-form-row-index":e.subFormRowIndex,"sub-form-col-index":e.subFormColIndex,"sub-form-row-id":e.subFormRowId},{default:require$$0$1.withCtx(()=>[require$$0$1.createElementVNode("div",_hoisted_1$B,[require$$0$1.createVNode(a,{ref:"fieldEditor",options:e.field.options.optionItems,modelValue:m.fieldModel,"onUpdate:modelValue":d[0]||(d[0]=r=>m.fieldModel=r),disabled:e.field.options.disabled,size:t.widgetSize,clearable:e.field.options.clearable,filterable:e.field.options.filterable,placeholder:e.field.options.placeholder||t.i18nt("render.hint.selectPlaceholder"),"show-all-levels":g.showFullPath,props:{checkStrictly:e.field.options.checkStrictly,multiple:e.field.options.multiple,expandTrigger:"hover"},onFocus:t.handleFocusCustomEvent,onBlur:t.handleBlurCustomEvent,onChange:t.handleChangeEvent},null,8,["options","modelValue","disabled","size","clearable","filterable","placeholder","show-all-levels","props","onFocus","onBlur","onChange"])])]),_:1},8,["designer","field","rules","design-state","parent-widget","parent-list","index-of-parent-list","sub-form-row-index","sub-form-col-index","sub-form-row-id"])}var cascaderWidget=_export_sfc$1(_sfc_main$33,[["render",_sfc_render$33],["__scopeId","data-v-ec070d7c"]]),__glob_0_1$3=Object.freeze(Object.defineProperty({__proto__:null,default:cascaderWidget},Symbol.toStringTag,{value:"Module"})),checkboxWidget_vue_vue_type_style_index_0_scoped_true_lang="";const _sfc_main$32={name:"checkbox-widget",componentName:"FieldWidget",mixins:[emitter,fieldMixin,i18n$1],props:{field:Object,parentWidget:Object,parentList:Array,indexOfParentList:Number,designer:Object,designState:{type:Boolean,default:!1},subFormRowIndex:{type:Number,default:-1},subFormColIndex:{type:Number,default:-1},subFormRowId:{type:String,default:""}},components:{FormItemWrapper},data(){return{oldFieldValue:null,fieldModel:null,rules:[]}},computed:{},beforeCreate(){},created(){this.initOptionItems(),this.initFieldModel(),this.registerToRefList(),this.initEventHandler(),this.buildFieldRules(),this.handleOnCreated()},mounted(){this.handleOnMounted()},beforeUnmount(){this.unregisterFromRefList()},methods:{}};function _sfc_render$32(t,d,e,h,m,g){const a=require$$0$1.resolveComponent("el-checkbox-button"),u=require$$0$1.resolveComponent("el-checkbox"),r=require$$0$1.resolveComponent("el-checkbox-group"),f=require$$0$1.resolveComponent("form-item-wrapper");return require$$0$1.openBlock(),require$$0$1.createBlock(f,{designer:e.designer,field:e.field,rules:m.rules,"design-state":e.designState,"parent-widget":e.parentWidget,"parent-list":e.parentList,"index-of-parent-list":e.indexOfParentList,"sub-form-row-index":e.subFormRowIndex,"sub-form-col-index":e.subFormColIndex,"sub-form-row-id":e.subFormRowId},{default:require$$0$1.withCtx(()=>[require$$0$1.createVNode(r,{ref:"fieldEditor",modelValue:m.fieldModel,"onUpdate:modelValue":d[0]||(d[0]=l=>m.fieldModel=l),disabled:e.field.options.disabled,size:t.widgetSize,onChange:t.handleChangeEvent},{default:require$$0$1.withCtx(()=>[e.field.options.buttonStyle?(require$$0$1.openBlock(!0),require$$0$1.createElementBlock(require$$0$1.Fragment,{key:0},require$$0$1.renderList(e.field.options.optionItems,(l,n)=>(require$$0$1.openBlock(),require$$0$1.createBlock(a,{key:n,label:l.value,disabled:l.disabled,border:e.field.options.border,style:require$$0$1.normalizeStyle({display:e.field.options.displayStyle})},{default:require$$0$1.withCtx(()=>[require$$0$1.createTextVNode(require$$0$1.toDisplayString(l.label),1)]),_:2},1032,["label","disabled","border","style"]))),128)):(require$$0$1.openBlock(!0),require$$0$1.createElementBlock(require$$0$1.Fragment,{key:1},require$$0$1.renderList(e.field.options.optionItems,(l,n)=>(require$$0$1.openBlock(),require$$0$1.createBlock(u,{key:n,label:l.value,disabled:l.disabled,border:e.field.options.border,style:require$$0$1.normalizeStyle({display:e.field.options.displayStyle})},{default:require$$0$1.withCtx(()=>[require$$0$1.createTextVNode(require$$0$1.toDisplayString(l.label),1)]),_:2},1032,["label","disabled","border","style"]))),128))]),_:1},8,["modelValue","disabled","size","onChange"])]),_:1},8,["designer","field","rules","design-state","parent-widget","parent-list","index-of-parent-list","sub-form-row-index","sub-form-col-index","sub-form-row-id"])}var checkboxWidget=_export_sfc$1(_sfc_main$32,[["render",_sfc_render$32],["__scopeId","data-v-716b0a6b"]]),__glob_0_2$3=Object.freeze(Object.defineProperty({__proto__:null,default:checkboxWidget},Symbol.toStringTag,{value:"Module"})),colorWidget_vue_vue_type_style_index_0_scoped_true_lang="";const _sfc_main$31={name:"color-widget",componentName:"FieldWidget",mixins:[emitter,fieldMixin,i18n$1],props:{field:Object,parentWidget:Object,parentList:Array,indexOfParentList:Number,designer:Object,designState:{type:Boolean,default:!1},subFormRowIndex:{type:Number,default:-1},subFormColIndex:{type:Number,default:-1},subFormRowId:{type:String,default:""}},components:{FormItemWrapper},data(){return{oldFieldValue:null,fieldModel:null,rules:[]}},computed:{},beforeCreate(){},created(){this.initFieldModel(),this.registerToRefList(),this.initEventHandler(),this.buildFieldRules(),this.handleOnCreated()},mounted(){this.handleOnMounted()},beforeUnmount(){this.unregisterFromRefList()},methods:{}};function _sfc_render$31(t,d,e,h,m,g){const a=require$$0$1.resolveComponent("el-color-picker"),u=require$$0$1.resolveComponent("form-item-wrapper");return require$$0$1.openBlock(),require$$0$1.createBlock(u,{designer:e.designer,field:e.field,rules:m.rules,"design-state":e.designState,"parent-widget":e.parentWidget,"parent-list":e.parentList,"index-of-parent-list":e.indexOfParentList,"sub-form-row-index":e.subFormRowIndex,"sub-form-col-index":e.subFormColIndex,"sub-form-row-id":e.subFormRowId},{default:require$$0$1.withCtx(()=>[require$$0$1.createVNode(a,{ref:"fieldEditor",modelValue:m.fieldModel,"onUpdate:modelValue":d[0]||(d[0]=r=>m.fieldModel=r),size:t.widgetSize,disabled:e.field.options.disabled,onChange:t.handleChangeEvent},null,8,["modelValue","size","disabled","onChange"])]),_:1},8,["designer","field","rules","design-state","parent-widget","parent-list","index-of-parent-list","sub-form-row-index","sub-form-col-index","sub-form-row-id"])}var colorWidget=_export_sfc$1(_sfc_main$31,[["render",_sfc_render$31],["__scopeId","data-v-8d04bd98"]]),__glob_0_3$3=Object.freeze(Object.defineProperty({__proto__:null,default:colorWidget},Symbol.toStringTag,{value:"Module"})),dateRangeWidget_vue_vue_type_style_index_0_scoped_true_lang="";const _sfc_main$30={name:"date-range-widget",componentName:"FieldWidget",mixins:[emitter,fieldMixin,i18n$1],props:{field:Object,parentWidget:Object,parentList:Array,indexOfParentList:Number,designer:Object,designState:{type:Boolean,default:!1},subFormRowIndex:{type:Number,default:-1},subFormColIndex:{type:Number,default:-1},subFormRowId:{type:String,default:""}},components:{FormItemWrapper},data(){return{oldFieldValue:null,fieldModel:null,rules:[]}},computed:{},beforeCreate(){},created(){this.initFieldModel(),this.registerToRefList(),this.initEventHandler(),this.buildFieldRules(),this.handleOnCreated()},mounted(){this.handleOnMounted()},beforeUnmount(){this.unregisterFromRefList()},methods:{}};function _sfc_render$30(t,d,e,h,m,g){const a=require$$0$1.resolveComponent("el-date-picker"),u=require$$0$1.resolveComponent("form-item-wrapper");return require$$0$1.openBlock(),require$$0$1.createBlock(u,{designer:e.designer,field:e.field,rules:m.rules,"design-state":e.designState,"parent-widget":e.parentWidget,"parent-list":e.parentList,"index-of-parent-list":e.indexOfParentList,"sub-form-row-index":e.subFormRowIndex,"sub-form-col-index":e.subFormColIndex,"sub-form-row-id":e.subFormRowId},{default:require$$0$1.withCtx(()=>[require$$0$1.createElementVNode("div",{class:require$$0$1.normalizeClass([e.field.options.autoFullWidth?"auto-full-width":""])},[require$$0$1.createVNode(a,{ref:"fieldEditor",type:e.field.options.type,modelValue:m.fieldModel,"onUpdate:modelValue":d[0]||(d[0]=r=>m.fieldModel=r),disabled:e.field.options.disabled,readonly:e.field.options.readonly,size:t.widgetSize,clearable:e.field.options.clearable,editable:e.field.options.editable,format:e.field.options.format,"value-format":e.field.options.valueFormat,"start-placeholder":e.field.options.startPlaceholder||t.i18nt("render.hint.startDatePlaceholder"),"end-placeholder":e.field.options.endPlaceholder||t.i18nt("render.hint.endDatePlaceholder"),onFocus:t.handleFocusCustomEvent,onBlur:t.handleBlurCustomEvent,onChange:t.handleChangeEvent},null,8,["type","modelValue","disabled","readonly","size","clearable","editable","format","value-format","start-placeholder","end-placeholder","onFocus","onBlur","onChange"])],2)]),_:1},8,["designer","field","rules","design-state","parent-widget","parent-list","index-of-parent-list","sub-form-row-index","sub-form-col-index","sub-form-row-id"])}var dateRangeWidget=_export_sfc$1(_sfc_main$30,[["render",_sfc_render$30],["__scopeId","data-v-21300a07"]]),__glob_0_4$3=Object.freeze(Object.defineProperty({__proto__:null,default:dateRangeWidget},Symbol.toStringTag,{value:"Module"})),dateWidget_vue_vue_type_style_index_0_scoped_true_lang="";const _sfc_main$2$={name:"date-widget",componentName:"FieldWidget",mixins:[emitter,fieldMixin,i18n$1],props:{field:Object,parentWidget:Object,parentList:Array,indexOfParentList:Number,designer:Object,designState:{type:Boolean,default:!1},subFormRowIndex:{type:Number,default:-1},subFormColIndex:{type:Number,default:-1},subFormRowId:{type:String,default:""}},components:{FormItemWrapper},data(){return{oldFieldValue:null,fieldModel:null,rules:[]}},computed:{},beforeCreate(){},created(){this.initFieldModel(),this.registerToRefList(),this.initEventHandler(),this.buildFieldRules(),this.handleOnCreated()},mounted(){this.handleOnMounted()},beforeUnmount(){this.unregisterFromRefList()},methods:{}};function _sfc_render$2$(t,d,e,h,m,g){const a=require$$0$1.resolveComponent("el-date-picker"),u=require$$0$1.resolveComponent("form-item-wrapper");return require$$0$1.openBlock(),require$$0$1.createBlock(u,{designer:e.designer,field:e.field,rules:m.rules,"design-state":e.designState,"parent-widget":e.parentWidget,"parent-list":e.parentList,"index-of-parent-list":e.indexOfParentList,"sub-form-row-index":e.subFormRowIndex,"sub-form-col-index":e.subFormColIndex,"sub-form-row-id":e.subFormRowId},{default:require$$0$1.withCtx(()=>[require$$0$1.createVNode(a,{ref:"fieldEditor",type:e.field.options.type,modelValue:m.fieldModel,"onUpdate:modelValue":d[0]||(d[0]=r=>m.fieldModel=r),class:require$$0$1.normalizeClass([e.field.options.autoFullWidth?"auto-full-width":""]),readonly:e.field.options.readonly,disabled:e.field.options.disabled,size:t.widgetSize,clearable:e.field.options.clearable,editable:e.field.options.editable,format:e.field.options.format,"value-format":e.field.options.valueFormat,placeholder:e.field.options.placeholder||t.i18nt("render.hint.datePlaceholder"),onFocus:t.handleFocusCustomEvent,onBlur:t.handleBlurCustomEvent,onChange:t.handleChangeEvent},null,8,["type","modelValue","class","readonly","disabled","size","clearable","editable","format","value-format","placeholder","onFocus","onBlur","onChange"])]),_:1},8,["designer","field","rules","design-state","parent-widget","parent-list","index-of-parent-list","sub-form-row-index","sub-form-col-index","sub-form-row-id"])}var dateWidget=_export_sfc$1(_sfc_main$2$,[["render",_sfc_render$2$],["__scopeId","data-v-75b85548"]]),__glob_0_5$3=Object.freeze(Object.defineProperty({__proto__:null,default:dateWidget},Symbol.toStringTag,{value:"Module"})),dividerWidget_vue_vue_type_style_index_0_scoped_true_lang="";const _sfc_main$2_={name:"divider-widget",componentName:"FieldWidget",mixins:[emitter,fieldMixin,i18n$1],props:{field:Object,parentWidget:Object,parentList:Array,indexOfParentList:Number,designer:Object,designState:{type:Boolean,default:!1},subFormRowIndex:{type:Number,default:-1},subFormColIndex:{type:Number,default:-1},subFormRowId:{type:String,default:""}},components:{StaticContentWrapper},computed:{},beforeCreate(){},created(){this.registerToRefList(),this.initEventHandler(),this.handleOnCreated()},mounted(){this.handleOnMounted()},beforeUnmount(){this.unregisterFromRefList()},methods:{}};function _sfc_render$2_(t,d,e,h,m,g){const a=require$$0$1.resolveComponent("el-divider"),u=require$$0$1.resolveComponent("static-content-wrapper");return require$$0$1.openBlock(),require$$0$1.createBlock(u,{designer:e.designer,field:e.field,"design-state":e.designState,"parent-widget":e.parentWidget,"parent-list":e.parentList,"index-of-parent-list":e.indexOfParentList,"sub-form-row-index":e.subFormRowIndex,"sub-form-col-index":e.subFormColIndex,"sub-form-row-id":e.subFormRowId},{default:require$$0$1.withCtx(()=>[require$$0$1.createVNode(a,{ref:"fieldEditor",direction:"horizontal","content-position":e.field.options.contentPosition},{default:require$$0$1.withCtx(()=>[require$$0$1.createTextVNode(require$$0$1.toDisplayString(e.field.options.label),1)]),_:1},8,["content-position"])]),_:1},8,["designer","field","design-state","parent-widget","parent-list","index-of-parent-list","sub-form-row-index","sub-form-col-index","sub-form-row-id"])}var dividerWidget=_export_sfc$1(_sfc_main$2_,[["render",_sfc_render$2_],["__scopeId","data-v-09a1b973"]]),__glob_0_6$2=Object.freeze(Object.defineProperty({__proto__:null,default:dividerWidget},Symbol.toStringTag,{value:"Module"})),fileUploadWidget_vue_vue_type_style_index_0_scoped_true_lang="";let selectFileText="'"+translate("render.hint.selectFile")+"'";const _sfc_main$2Z={name:"file-upload-widget",componentName:"FieldWidget",mixins:[emitter,fieldMixin,i18n$1],props:{field:Object,parentWidget:Object,parentList:Array,indexOfParentList:Number,designer:Object,designState:{type:Boolean,default:!1},subFormRowIndex:{type:Number,default:-1},subFormColIndex:{type:Number,default:-1},subFormRowId:{type:String,default:""}},components:{SvgIcon,FormItemWrapper},data(){return{oldFieldValue:null,fieldModel:[],rules:[],uploadHeaders:{},uploadData:{key:""},fileList:[],uploadBtnHidden:!1,styleVariables:{"--select-file-action":selectFileText}}},computed:{realUploadURL(){let t=this.field.options.uploadURL;if(!!t&&(t.indexOf("DSV.")>-1||t.indexOf("DSV[")>-1)){let d=this.getGlobalDsv();return console.log("test DSV: ",d),evalFn(this.field.options.uploadURL,d)}return this.field.options.uploadURL}},beforeCreate(){},created(){this.initFieldModel(),this.registerToRefList(),this.initEventHandler(),this.buildFieldRules(),this.handleOnCreated()},mounted(){this.handleOnMounted()},beforeUnmount(){this.unregisterFromRefList()},methods:{handleFileExceed(){let t=this.field.options.limit;this.$message.warning(this.i18nt("render.hint.uploadExceed").replace("${uploadLimit}",t))},beforeFileUpload(t){let d=!1,e=t.name.substring(t.name.lastIndexOf(".")+1);if(!!this.field.options&&!!this.field.options.fileTypes){let g=this.field.options.fileTypes;g.length>0&&(d=g.some(a=>e.toLowerCase()===a.toLowerCase()))}if(!d)return this.$message.error(this.i18nt("render.hint.unsupportedFileType")+e),!1;let h=!1,m=5;return!!this.field.options&&!!this.field.options.fileMaxSize&&(m=this.field.options.fileMaxSize),h=t.size/1024/1024<=m,h?(this.uploadData.key=t.name,this.handleOnBeforeUpload(t)):(this.$message.error(this.i18nt("render.hint.fileSizeExceed")+m+"MB"),!1)},handleOnBeforeUpload(t){if(this.field.options.onBeforeUpload){let e=new Function("file",this.field.options.onBeforeUpload).call(this,t);return typeof e=="boolean"?e:!0}return!0},updateFieldModelAndEmitDataChangeForUpload(t,d,e){let h=deepClone(this.fieldModel);!!d&&!!d.name&&!!d.url?this.fieldModel.push({name:d.name,url:d.url}):!!e&&!!e.name&&!!e.url?this.fieldModel.push({name:e.name,url:e.url}):this.fieldModel=deepClone(t),this.syncUpdateFormModel(this.fieldModel),this.emitFieldDataChange(this.fieldModel,h)},handleFileUpload(t,d,e){if(d.status==="success"){let h=null;this.field.options.onUploadSuccess&&(h=new Function("result","file","fileList",this.field.options.onUploadSuccess).call(this,t,d,e)),this.updateFieldModelAndEmitDataChangeForUpload(e,h,t),!!h&&!!h.name?d.name=h.name:d.name=d.name||t.name||t.fileName||t.filename,!!h&&!!h.url?d.url=h.url:d.url=d.url||t.url,this.fileList=deepClone(e),this.uploadBtnHidden=e.length>=this.field.options.limit}},updateFieldModelAndEmitDataChangeForRemove(t,d){let e=deepClone(this.fieldModel);this.fieldModel.splice(t,1),this.syncUpdateFormModel(this.fieldModel),this.emitFieldDataChange(this.fieldModel,e)},removeUploadFile(t,d,e){let h=-1,m=null;this.fileList.forEach((g,a)=>{g.name===t&&(g.url===d||!!e&&g.uid===e)&&(h=a,m=g)}),h>=0&&(this.fileList.splice(h,1),this.updateFieldModelAndEmitDataChangeForRemove(h,this.fileList),this.uploadBtnHidden=this.fileList.length>=this.field.options.limit,this.field.options.onFileRemove&&new Function("file","fileList",this.field.options.onFileRemove).call(this,m,this.fileList))},handleUploadError(t,d,e){this.field.options.onUploadError?new Function("error","file","fileList",this.field.options.onUploadError).call(this,t,d,e):this.$message({message:this.i18nt("render.hint.uploadError")+t,duration:3e3,type:"error"})}}},_withScopeId$3=t=>(require$$0$1.pushScopeId("data-v-b6b1e8a8"),t=t(),require$$0$1.popScopeId(),t),_hoisted_1$A={key:0,class:"el-upload__tip"},_hoisted_2$o=_withScopeId$3(()=>require$$0$1.createElementVNode("i",{class:"el-icon-plus avatar-uploader-icon"},null,-1)),_hoisted_3$j={class:"upload-file-list"},_hoisted_4$c=["title"],_hoisted_5$a=["href"],_hoisted_6$9=["title"],_hoisted_7$6=["title","onClick"];function _sfc_render$2Z(t,d,e,h,m,g){const a=require$$0$1.resolveComponent("svg-icon"),u=require$$0$1.resolveComponent("el-upload"),r=require$$0$1.resolveComponent("form-item-wrapper");return require$$0$1.openBlock(),require$$0$1.createBlock(r,{designer:e.designer,field:e.field,rules:m.rules,"design-state":e.designState,"parent-widget":e.parentWidget,"parent-list":e.parentList,"index-of-parent-list":e.indexOfParentList,"sub-form-row-index":e.subFormRowIndex,"sub-form-col-index":e.subFormColIndex,"sub-form-row-id":e.subFormRowId},{default:require$$0$1.withCtx(()=>[require$$0$1.createVNode(u,{ref:"fieldEditor",disabled:e.field.options.disabled,style:require$$0$1.normalizeStyle(m.styleVariables),class:require$$0$1.normalizeClass(["dynamicPseudoAfter",{hideUploadDiv:m.uploadBtnHidden}]),action:g.realUploadURL,headers:m.uploadHeaders,data:m.uploadData,"with-credentials":e.field.options.withCredentials,multiple:e.field.options.multipleSelect,"file-list":m.fileList,"show-file-list":e.field.options.showFileList,limit:e.field.options.limit,"on-exceed":g.handleFileExceed,"before-upload":g.beforeFileUpload,"on-success":g.handleFileUpload,"on-error":g.handleUploadError},{tip:require$$0$1.withCtx(()=>[e.field.options.uploadTip?(require$$0$1.openBlock(),require$$0$1.createElementBlock("div",_hoisted_1$A,require$$0$1.toDisplayString(e.field.options.uploadTip),1)):require$$0$1.createCommentVNode("",!0)]),default:require$$0$1.withCtx(()=>[require$$0$1.createVNode(a,{"icon-class":"el-plus"}),_hoisted_2$o]),file:require$$0$1.withCtx(({file:f})=>[require$$0$1.createElementVNode("div",_hoisted_3$j,[require$$0$1.createElementVNode("span",{class:"upload-file-name",title:f.name},require$$0$1.toDisplayString(f.name),9,_hoisted_4$c),require$$0$1.createElementVNode("a",{href:f.url,download:"",target:"_blank"},[require$$0$1.createElementVNode("span",{class:"el-icon-download file-action",title:t.i18nt("render.hint.downloadFile")},[require$$0$1.createVNode(a,{"icon-class":"el-download"})],8,_hoisted_6$9)],8,_hoisted_5$a),e.field.options.disabled?require$$0$1.createCommentVNode("",!0):(require$$0$1.openBlock(),require$$0$1.createElementBlock("span",{key:0,class:"file-action",title:t.i18nt("render.hint.removeFile"),onClick:l=>g.removeUploadFile(f.name,f.url,f.uid)},[require$$0$1.createVNode(a,{"icon-class":"el-delete"})],8,_hoisted_7$6))])]),_:1},8,["disabled","style","action","headers","data","with-credentials","multiple","file-list","show-file-list","class","limit","on-exceed","before-upload","on-success","on-error"])]),_:1},8,["designer","field","rules","design-state","parent-widget","parent-list","index-of-parent-list","sub-form-row-index","sub-form-col-index","sub-form-row-id"])}var fileUploadWidget=_export_sfc$1(_sfc_main$2Z,[["render",_sfc_render$2Z],["__scopeId","data-v-b6b1e8a8"]]),__glob_0_7$1=Object.freeze(Object.defineProperty({__proto__:null,default:fileUploadWidget},Symbol.toStringTag,{value:"Module"})),htmlTextWidget_vue_vue_type_style_index_0_scoped_true_lang="";const _sfc_main$2Y={name:"html-text-widget",componentName:"FieldWidget",mixins:[emitter,fieldMixin,i18n$1],props:{field:Object,parentWidget:Object,parentList:Array,indexOfParentList:Number,designer:Object,designState:{type:Boolean,default:!1},subFormRowIndex:{type:Number,default:-1},subFormColIndex:{type:Number,default:-1},subFormRowId:{type:String,default:""}},components:{StaticContentWrapper},computed:{},beforeCreate(){},created(){this.registerToRefList(),this.initEventHandler(),this.handleOnCreated()},mounted(){this.handleOnMounted()},beforeUnmount(){this.unregisterFromRefList()},methods:{}},_hoisted_1$z=["innerHTML"];function _sfc_render$2Y(t,d,e,h,m,g){const a=require$$0$1.resolveComponent("static-content-wrapper");return require$$0$1.openBlock(),require$$0$1.createBlock(a,{designer:e.designer,field:e.field,"design-state":e.designState,"parent-widget":e.parentWidget,"parent-list":e.parentList,"index-of-parent-list":e.indexOfParentList,"sub-form-row-index":e.subFormRowIndex,"sub-form-col-index":e.subFormColIndex,"sub-form-row-id":e.subFormRowId},{default:require$$0$1.withCtx(()=>[require$$0$1.createElementVNode("div",{ref:"fieldEditor",innerHTML:e.field.options.htmlContent},null,8,_hoisted_1$z)]),_:1},8,["designer","field","design-state","parent-widget","parent-list","index-of-parent-list","sub-form-row-index","sub-form-col-index","sub-form-row-id"])}var htmlTextWidget=_export_sfc$1(_sfc_main$2Y,[["render",_sfc_render$2Y],["__scopeId","data-v-3d941b4e"]]),__glob_0_9$1=Object.freeze(Object.defineProperty({__proto__:null,default:htmlTextWidget},Symbol.toStringTag,{value:"Module"})),inputWidget_vue_vue_type_style_index_0_scoped_true_lang="";const _sfc_main$2X={name:"input-widget",componentName:"FieldWidget",mixins:[emitter,fieldMixin,i18n$1],props:{field:Object,parentWidget:Object,parentList:Array,indexOfParentList:Number,designer:Object,designState:{type:Boolean,default:!1},subFormRowIndex:{type:Number,default:-1},subFormColIndex:{type:Number,default:-1},subFormRowId:{type:String,default:""}},components:{FormItemWrapper,SvgIcon},data(){return{oldFieldValue:null,fieldModel:null,rules:[]}},computed:{inputType(){return this.field.options.type==="number"?"text":this.field.options.type}},beforeCreate(){},created(){this.initFieldModel(),this.registerToRefList(),this.initEventHandler(),this.buildFieldRules(),this.handleOnCreated()},mounted(){this.handleOnMounted()},beforeUnmount(){this.unregisterFromRefList()},methods:{}};function _sfc_render$2X(t,d,e,h,m,g){const a=require$$0$1.resolveComponent("svg-icon"),u=require$$0$1.resolveComponent("el-button"),r=require$$0$1.resolveComponent("el-input"),f=require$$0$1.resolveComponent("form-item-wrapper");return require$$0$1.openBlock(),require$$0$1.createBlock(f,{designer:e.designer,field:e.field,rules:m.rules,"design-state":e.designState,"parent-widget":e.parentWidget,"parent-list":e.parentList,"index-of-parent-list":e.indexOfParentList,"sub-form-row-index":e.subFormRowIndex,"sub-form-col-index":e.subFormColIndex,"sub-form-row-id":e.subFormRowId},{default:require$$0$1.withCtx(()=>[require$$0$1.createVNode(r,{ref:"fieldEditor",modelValue:m.fieldModel,"onUpdate:modelValue":d[0]||(d[0]=l=>m.fieldModel=l),disabled:e.field.options.disabled,readonly:e.field.options.readonly,size:t.widgetSize,class:"hide-spin-button",type:g.inputType,"show-password":e.field.options.showPassword,placeholder:e.field.options.placeholder,clearable:e.field.options.clearable,minlength:e.field.options.minLength,maxlength:e.field.options.maxLength,"show-word-limit":e.field.options.showWordLimit,"prefix-icon":e.field.options.prefixIcon,"suffix-icon":e.field.options.suffixIcon,onFocus:t.handleFocusCustomEvent,onBlur:t.handleBlurCustomEvent,onInput:t.handleInputCustomEvent,onChange:t.handleChangeEvent},require$$0$1.createSlots({_:2},[e.field.options.appendButton?{name:"append",fn:require$$0$1.withCtx(()=>[require$$0$1.createVNode(u,{disabled:e.field.options.disabled||e.field.options.appendButtonDisabled,onClick:t.emitAppendButtonClick},{default:require$$0$1.withCtx(()=>[require$$0$1.createVNode(a,{"icon-class":e.field.options.buttonIcon},null,8,["icon-class"])]),_:1},8,["disabled","onClick"])]),key:"0"}:void 0]),1032,["modelValue","disabled","readonly","size","type","show-password","placeholder","clearable","minlength","maxlength","show-word-limit","prefix-icon","suffix-icon","onFocus","onBlur","onInput","onChange"])]),_:1},8,["designer","field","rules","design-state","parent-widget","parent-list","index-of-parent-list","sub-form-row-index","sub-form-col-index","sub-form-row-id"])}var inputWidget=_export_sfc$1(_sfc_main$2X,[["render",_sfc_render$2X],["__scopeId","data-v-0aad1a31"]]),__glob_0_10$1=Object.freeze(Object.defineProperty({__proto__:null,default:inputWidget},Symbol.toStringTag,{value:"Module"})),numberWidget_vue_vue_type_style_index_0_scoped_true_lang="";const _sfc_main$2W={name:"number-widget",componentName:"FieldWidget",mixins:[emitter,fieldMixin,i18n$1],props:{field:Object,parentWidget:Object,parentList:Array,indexOfParentList:Number,designer:Object,designState:{type:Boolean,default:!1},subFormRowIndex:{type:Number,default:-1},subFormColIndex:{type:Number,default:-1},subFormRowId:{type:String,default:""}},components:{FormItemWrapper},data(){return{oldFieldValue:null,fieldModel:null,rules:[]}},computed:{},beforeCreate(){},created(){this.initFieldModel(),this.registerToRefList(),this.initEventHandler(),this.buildFieldRules(),this.handleOnCreated()},mounted(){this.handleOnMounted()},beforeUnmount(){this.unregisterFromRefList()},methods:{}};function _sfc_render$2W(t,d,e,h,m,g){const a=require$$0$1.resolveComponent("el-input-number"),u=require$$0$1.resolveComponent("form-item-wrapper");return require$$0$1.openBlock(),require$$0$1.createBlock(u,{designer:e.designer,field:e.field,rules:m.rules,"design-state":e.designState,"parent-widget":e.parentWidget,"parent-list":e.parentList,"index-of-parent-list":e.indexOfParentList,"sub-form-row-index":e.subFormRowIndex,"sub-form-col-index":e.subFormColIndex,"sub-form-row-id":e.subFormRowId},{default:require$$0$1.withCtx(()=>[require$$0$1.createVNode(a,{ref:"fieldEditor",modelValue:m.fieldModel,"onUpdate:modelValue":d[0]||(d[0]=r=>m.fieldModel=r),class:"full-width-input",disabled:e.field.options.disabled,size:t.widgetSize,"controls-position":e.field.options.controlsPosition,placeholder:e.field.options.placeholder,min:e.field.options.min,max:e.field.options.max,precision:e.field.options.precision,step:e.field.options.step,onFocus:t.handleFocusCustomEvent,onBlur:t.handleBlurCustomEvent,onChange:t.handleChangeEvent},null,8,["modelValue","disabled","size","controls-position","placeholder","min","max","precision","step","onFocus","onBlur","onChange"])]),_:1},8,["designer","field","rules","design-state","parent-widget","parent-list","index-of-parent-list","sub-form-row-index","sub-form-col-index","sub-form-row-id"])}var numberWidget=_export_sfc$1(_sfc_main$2W,[["render",_sfc_render$2W],["__scopeId","data-v-0b9bc82f"]]),__glob_0_11$1=Object.freeze(Object.defineProperty({__proto__:null,default:numberWidget},Symbol.toStringTag,{value:"Module"})),pictureUploadWidget_vue_vue_type_style_index_0_scoped_true_lang="";const _sfc_main$2V={name:"picture-upload-widget",componentName:"FieldWidget",mixins:[emitter,fieldMixin,i18n$1],props:{field:Object,parentWidget:Object,parentList:Array,indexOfParentList:Number,designer:Object,designState:{type:Boolean,default:!1},subFormRowIndex:{type:Number,default:-1},subFormColIndex:{type:Number,default:-1},subFormRowId:{type:String,default:""}},components:{FormItemWrapper,SvgIcon},data(){return{oldFieldValue:null,fieldModel:[],rules:[],uploadHeaders:{},uploadData:{key:""},fileList:[],fileListBeforeRemove:[],uploadBtnHidden:!1,previewIndex:1}},computed:{previewList(){return this.fileList.map(t=>t.url)},realUploadURL(){let t=this.field.options.uploadURL;if(!!t&&(t.indexOf("DSV.")>-1||t.indexOf("DSV[")>-1)){let d=this.getGlobalDsv();return console.log("test DSV: ",d),evalFn(this.field.options.uploadURL,d)}return this.field.options.uploadURL}},beforeCreate(){},created(){this.initFieldModel(),this.registerToRefList(),this.initEventHandler(),this.buildFieldRules(),this.handleOnCreated()},mounted(){this.handleOnMounted()},beforeUnmount(){this.unregisterFromRefList()},methods:{handlePictureExceed(){let t=this.field.options.limit;this.$message.warning(this.i18nt("render.hint.uploadExceed").replace("${uploadLimit}",t))},beforePictureUpload(t){let d=!1;if(!!this.field.options&&!!this.field.options.fileTypes){let m=this.field.options.fileTypes;m.length>0&&(d=m.some(g=>t.type==="image/"+g))}if(!d)return this.$message.error(this.i18nt("render.hint.unsupportedFileType")+t.type),!1;let e=!1,h=5;return!!this.field.options&&!!this.field.options.fileMaxSize&&(h=this.field.options.fileMaxSize),e=t.size/1024/1024<=h,e?(this.uploadData.key=t.name,this.handleOnBeforeUpload(t)):(this.$message.error(this.$("render.hint.fileSizeExceed")+h+"MB"),!1)},handleOnBeforeUpload(t){if(this.field.options.onBeforeUpload){let e=new Function("file",this.field.options.onBeforeUpload).call(this,t);return typeof e=="boolean"?e:!0}return!0},updateFieldModelAndEmitDataChangeForUpload(t,d,e){let h=deepClone(this.fieldModel);!!d&&!!d.name&&!!d.url?this.fieldModel.push({name:d.name,url:d.url}):!!e&&!!e.name&&!!e.url?this.fieldModel.push({name:e.name,url:e.url}):this.fieldModel=deepClone(t),this.syncUpdateFormModel(this.fieldModel),this.emitFieldDataChange(this.fieldModel,h)},handlePictureUpload(t,d,e){if(d.status==="success"){let h=null;this.field.options.onUploadSuccess&&(h=new Function("result","file","fileList",this.field.options.onUploadSuccess).call(this,t,d,e)),this.updateFieldModelAndEmitDataChangeForUpload(e,h,t),this.fileList=deepClone(e),this.uploadBtnHidden=e.length>=this.field.options.limit}},updateFieldModelAndEmitDataChangeForRemove(t){let d=deepClone(this.fieldModel),e=-1;this.fileListBeforeRemove.map((h,m)=>{h.name===t.name&&(h.url===t.url||!!h.uid&&h.uid===t.uid)&&(e=m)}),e>-1&&this.fieldModel.splice(e,1),this.syncUpdateFormModel(this.fieldModel),this.emitFieldDataChange(this.fieldModel,d)},handleBeforeRemove(t){this.fileListBeforeRemove=deepClone(t)},handlePictureRemove(t){this.handleBeforeRemove(this.fileList),this.fileList.splice(this.fileList.indexOf(t),1),this.updateFieldModelAndEmitDataChangeForRemove(t);let d=deepClone(this.fileList);this.uploadBtnHidden=d.length>=this.field.options.limit,this.field.options.onFileRemove&&new Function("file","fileList",this.field.options.onFileRemove).call(this,t,d)},handleUploadError(t,d,e){this.field.options.onUploadError?new Function("error","file","fileList",this.field.options.onUploadError).call(this,t,d,e):this.$message({message:this.i18nt("render.hint.uploadError")+t,duration:3e3,type:"error"})},handlePictureCardPreview({url:t}){this.previewIndex=this.previewList.indexOf(t),this.$refs.imageRef.$el.children[0].click()}}},_hoisted_1$y={class:"el-upload-list__item-status-label"},_hoisted_2$n={class:"el-icon--upload-success",style:{color:"#FFF"}},_hoisted_3$i={class:"el-upload-list__item-actions"},_hoisted_4$b=["onClick"],_hoisted_5$9=["onClick"],_hoisted_6$8={key:0,class:"el-upload__tip"},_hoisted_7$5={class:"uploader-icon"};function _sfc_render$2V(t,d,e,h,m,g){const a=require$$0$1.resolveComponent("el-image"),u=require$$0$1.resolveComponent("svg-icon"),r=require$$0$1.resolveComponent("el-upload"),f=require$$0$1.resolveComponent("form-item-wrapper");return require$$0$1.openBlock(),require$$0$1.createBlock(f,{designer:e.designer,field:e.field,rules:m.rules,"design-state":e.designState,"parent-widget":e.parentWidget,"parent-list":e.parentList,"index-of-parent-list":e.indexOfParentList,"sub-form-row-index":e.subFormRowIndex,"sub-form-col-index":e.subFormColIndex,"sub-form-row-id":e.subFormRowId},{default:require$$0$1.withCtx(()=>[require$$0$1.createVNode(r,{ref:"fieldEditor",disabled:e.field.options.disabled,action:g.realUploadURL,headers:m.uploadHeaders,data:m.uploadData,"with-credentials":e.field.options.withCredentials,multiple:e.field.options.multipleSelect,"file-list":m.fileList,"show-file-list":e.field.options.showFileList,"list-type":"picture-card",class:require$$0$1.normalizeClass({hideUploadDiv:m.uploadBtnHidden}),limit:e.field.options.limit,"on-exceed":g.handlePictureExceed,"before-upload":g.beforePictureUpload,"on-preview":g.handlePictureCardPreview,"on-success":g.handlePictureUpload,"on-error":g.handleUploadError},{file:require$$0$1.withCtx(({file:l})=>[require$$0$1.createVNode(a,{ref:"imageRef",style:{width:"100%",height:"100%"},src:l.url,"preview-src-list":g.previewList,"initial-index":m.previewIndex,fit:"cover","preview-teleported":""},null,8,["src","preview-src-list","initial-index"]),require$$0$1.createElementVNode("label",_hoisted_1$y,[require$$0$1.createElementVNode("i",_hoisted_2$n,[require$$0$1.createVNode(u,{class:"","icon-class":"el-check"})])]),require$$0$1.createElementVNode("span",_hoisted_3$i,[require$$0$1.createElementVNode("span",{class:"el-upload-list__item-preview",onClick:n=>g.handlePictureCardPreview(l)},[require$$0$1.createVNode(u,{"icon-class":"el-zoom-in"})],8,_hoisted_4$b),require$$0$1.createElementVNode("span",{class:"el-upload-list__item-delete",onClick:n=>g.handlePictureRemove(l)},[require$$0$1.createVNode(u,{"icon-class":"el-delete"})],8,_hoisted_5$9)])]),tip:require$$0$1.withCtx(()=>[e.field.options.uploadTip?(require$$0$1.openBlock(),require$$0$1.createElementBlock("div",_hoisted_6$8,require$$0$1.toDisplayString(e.field.options.uploadTip),1)):require$$0$1.createCommentVNode("",!0)]),default:require$$0$1.withCtx(()=>[require$$0$1.createElementVNode("div",_hoisted_7$5,[require$$0$1.createVNode(u,{"icon-class":"el-plus"})])]),_:1},8,["disabled","action","headers","data","with-credentials","multiple","file-list","show-file-list","class","limit","on-exceed","before-upload","on-preview","on-success","on-error"])]),_:1},8,["designer","field","rules","design-state","parent-widget","parent-list","index-of-parent-list","sub-form-row-index","sub-form-col-index","sub-form-row-id"])}var pictureUploadWidget=_export_sfc$1(_sfc_main$2V,[["render",_sfc_render$2V],["__scopeId","data-v-3393010d"]]),__glob_0_12$1=Object.freeze(Object.defineProperty({__proto__:null,default:pictureUploadWidget},Symbol.toStringTag,{value:"Module"})),radioWidget_vue_vue_type_style_index_0_scoped_true_lang="";const _sfc_main$2U={name:"radio-widget",componentName:"FieldWidget",mixins:[emitter,fieldMixin,i18n$1],props:{field:Object,parentWidget:Object,parentList:Array,indexOfParentList:Number,designer:Object,designState:{type:Boolean,default:!1},subFormRowIndex:{type:Number,default:-1},subFormColIndex:{type:Number,default:-1},subFormRowId:{type:String,default:""}},components:{FormItemWrapper},data(){return{oldFieldValue:null,fieldModel:null,rules:[]}},computed:{},beforeCreate(){},created(){this.initOptionItems(),this.initFieldModel(),this.registerToRefList(),this.initEventHandler(),this.buildFieldRules(),this.handleOnCreated()},mounted(){this.handleOnMounted()},beforeUnmount(){this.unregisterFromRefList()},methods:{}};function _sfc_render$2U(t,d,e,h,m,g){const a=require$$0$1.resolveComponent("el-radio-button"),u=require$$0$1.resolveComponent("el-radio"),r=require$$0$1.resolveComponent("el-radio-group"),f=require$$0$1.resolveComponent("form-item-wrapper");return require$$0$1.openBlock(),require$$0$1.createBlock(f,{designer:e.designer,field:e.field,rules:m.rules,"design-state":e.designState,"parent-widget":e.parentWidget,"parent-list":e.parentList,"index-of-parent-list":e.indexOfParentList,"sub-form-row-index":e.subFormRowIndex,"sub-form-col-index":e.subFormColIndex,"sub-form-row-id":e.subFormRowId},{default:require$$0$1.withCtx(()=>[require$$0$1.createVNode(r,{ref:"fieldEditor",modelValue:m.fieldModel,"onUpdate:modelValue":d[0]||(d[0]=l=>m.fieldModel=l),class:require$$0$1.normalizeClass({"radio-group-block":e.field.options.displayStyle==="block"}),disabled:e.field.options.disabled,size:t.widgetSize,onChange:t.handleChangeEvent},{default:require$$0$1.withCtx(()=>[e.field.options.buttonStyle?(require$$0$1.openBlock(!0),require$$0$1.createElementBlock(require$$0$1.Fragment,{key:0},require$$0$1.renderList(e.field.options.optionItems,(l,n)=>(require$$0$1.openBlock(),require$$0$1.createBlock(a,{key:n,label:l.value,disabled:l.disabled,border:e.field.options.border,style:require$$0$1.normalizeStyle({display:e.field.options.displayStyle})},{default:require$$0$1.withCtx(()=>[require$$0$1.createTextVNode(require$$0$1.toDisplayString(l.label),1)]),_:2},1032,["label","disabled","border","style"]))),128)):(require$$0$1.openBlock(!0),require$$0$1.createElementBlock(require$$0$1.Fragment,{key:1},require$$0$1.renderList(e.field.options.optionItems,(l,n)=>(require$$0$1.openBlock(),require$$0$1.createBlock(u,{key:n,label:l.value,disabled:l.disabled,border:e.field.options.border,style:require$$0$1.normalizeStyle({display:e.field.options.displayStyle})},{default:require$$0$1.withCtx(()=>[require$$0$1.createTextVNode(require$$0$1.toDisplayString(l.label),1)]),_:2},1032,["label","disabled","border","style"]))),128))]),_:1},8,["modelValue","class","disabled","size","onChange"])]),_:1},8,["designer","field","rules","design-state","parent-widget","parent-list","index-of-parent-list","sub-form-row-index","sub-form-col-index","sub-form-row-id"])}var radioWidget=_export_sfc$1(_sfc_main$2U,[["render",_sfc_render$2U],["__scopeId","data-v-253adc5e"]]),__glob_0_13$1=Object.freeze(Object.defineProperty({__proto__:null,default:radioWidget},Symbol.toStringTag,{value:"Module"})),rateWidget_vue_vue_type_style_index_0_scoped_true_lang="";const _sfc_main$2T={name:"rate-widget",componentName:"FieldWidget",mixins:[emitter,fieldMixin,i18n$1],props:{field:Object,parentWidget:Object,parentList:Array,indexOfParentList:Number,designer:Object,designState:{type:Boolean,default:!1},subFormRowIndex:{type:Number,default:-1},subFormColIndex:{type:Number,default:-1},subFormRowId:{type:String,default:""}},components:{FormItemWrapper},data(){return{oldFieldValue:null,fieldModel:null,rules:[]}},computed:{},beforeCreate(){},created(){this.initFieldModel(),this.registerToRefList(),this.initEventHandler(),this.buildFieldRules(),this.handleOnCreated()},mounted(){this.handleOnMounted()},beforeUnmount(){this.unregisterFromRefList()},methods:{}};function _sfc_render$2T(t,d,e,h,m,g){const a=require$$0$1.resolveComponent("el-rate"),u=require$$0$1.resolveComponent("form-item-wrapper");return require$$0$1.openBlock(),require$$0$1.createBlock(u,{designer:e.designer,field:e.field,rules:m.rules,"design-state":e.designState,"parent-widget":e.parentWidget,"parent-list":e.parentList,"index-of-parent-list":e.indexOfParentList,"sub-form-row-index":e.subFormRowIndex,"sub-form-col-index":e.subFormColIndex,"sub-form-row-id":e.subFormRowId},{default:require$$0$1.withCtx(()=>[require$$0$1.createVNode(a,{ref:"fieldEditor",modelValue:m.fieldModel,"onUpdate:modelValue":d[0]||(d[0]=r=>m.fieldModel=r),disabled:e.field.options.disabled,max:e.field.options.max,"low-threshold":e.field.options.lowThreshold,"high-threshold":e.field.options.highThreshold,"allow-half":e.field.options.allowHalf,"show-text":e.field.options.showText,"show-score":e.field.options.showScore,onChange:t.handleChangeEvent},null,8,["modelValue","disabled","max","low-threshold","high-threshold","allow-half","show-text","show-score","onChange"])]),_:1},8,["designer","field","rules","design-state","parent-widget","parent-list","index-of-parent-list","sub-form-row-index","sub-form-col-index","sub-form-row-id"])}var rateWidget=_export_sfc$1(_sfc_main$2T,[["render",_sfc_render$2T],["__scopeId","data-v-409c0e8b"]]),__glob_0_14$1=Object.freeze(Object.defineProperty({__proto__:null,default:rateWidget},Symbol.toStringTag,{value:"Module"})),quill={exports:{}};/*! + * Quill Editor v1.3.7 + * https://quilljs.com/ + * Copyright (c) 2014, Jason Chen + * Copyright (c) 2013, salesforce.com + */(function(t,d){(function(h,m){t.exports=m()})(typeof self!="undefined"?self:commonjsGlobal,function(){return function(e){var h={};function m(g){if(h[g])return h[g].exports;var a=h[g]={i:g,l:!1,exports:{}};return e[g].call(a.exports,a,a.exports,m),a.l=!0,a.exports}return m.m=e,m.c=h,m.d=function(g,a,u){m.o(g,a)||Object.defineProperty(g,a,{configurable:!1,enumerable:!0,get:u})},m.n=function(g){var a=g&&g.__esModule?function(){return g.default}:function(){return g};return m.d(a,"a",a),a},m.o=function(g,a){return Object.prototype.hasOwnProperty.call(g,a)},m.p="",m(m.s=109)}([function(e,h,m){Object.defineProperty(h,"__esModule",{value:!0});var g=m(17),a=m(18),u=m(19),r=m(45),f=m(46),l=m(47),n=m(48),i=m(49),o=m(12),s=m(32),c=m(33),p=m(31),$=m(1),v={Scope:$.Scope,create:$.create,find:$.find,query:$.query,register:$.register,Container:g.default,Format:a.default,Leaf:u.default,Embed:n.default,Scroll:r.default,Block:l.default,Inline:f.default,Text:i.default,Attributor:{Attribute:o.default,Class:s.default,Style:c.default,Store:p.default}};h.default=v},function(e,h,m){var g=this&&this.__extends||function(){var p=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function($,v){$.__proto__=v}||function($,v){for(var C in v)v.hasOwnProperty(C)&&($[C]=v[C])};return function($,v){p($,v);function C(){this.constructor=$}$.prototype=v===null?Object.create(v):(C.prototype=v.prototype,new C)}}();Object.defineProperty(h,"__esModule",{value:!0});var a=function(p){g($,p);function $(v){var C=this;return v="[Parchment] "+v,C=p.call(this,v)||this,C.message=v,C.name=C.constructor.name,C}return $}(Error);h.ParchmentError=a;var u={},r={},f={},l={};h.DATA_KEY="__blot";var n;(function(p){p[p.TYPE=3]="TYPE",p[p.LEVEL=12]="LEVEL",p[p.ATTRIBUTE=13]="ATTRIBUTE",p[p.BLOT=14]="BLOT",p[p.INLINE=7]="INLINE",p[p.BLOCK=11]="BLOCK",p[p.BLOCK_BLOT=10]="BLOCK_BLOT",p[p.INLINE_BLOT=6]="INLINE_BLOT",p[p.BLOCK_ATTRIBUTE=9]="BLOCK_ATTRIBUTE",p[p.INLINE_ATTRIBUTE=5]="INLINE_ATTRIBUTE",p[p.ANY=15]="ANY"})(n=h.Scope||(h.Scope={}));function i(p,$){var v=s(p);if(v==null)throw new a("Unable to create "+p+" blot");var C=v,y=p instanceof Node||p.nodeType===Node.TEXT_NODE?p:C.create($);return new C(y,$)}h.create=i;function o(p,$){return $===void 0&&($=!1),p==null?null:p[h.DATA_KEY]!=null?p[h.DATA_KEY].blot:$?o(p.parentNode,$):null}h.find=o;function s(p,$){$===void 0&&($=n.ANY);var v;if(typeof p=="string")v=l[p]||u[p];else if(p instanceof Text||p.nodeType===Node.TEXT_NODE)v=l.text;else if(typeof p=="number")p&n.LEVEL&n.BLOCK?v=l.block:p&n.LEVEL&n.INLINE&&(v=l.inline);else if(p instanceof HTMLElement){var C=(p.getAttribute("class")||"").split(/\s+/);for(var y in C)if(v=r[C[y]],v)break;v=v||f[p.tagName]}return v==null?null:$&n.LEVEL&v.scope&&$&n.TYPE&v.scope?v:null}h.query=s;function c(){for(var p=[],$=0;$1)return p.map(function(y){return c(y)});var v=p[0];if(typeof v.blotName!="string"&&typeof v.attrName!="string")throw new a("Invalid definition");if(v.blotName==="abstract")throw new a("Cannot register abstract class");if(l[v.blotName||v.attrName]=v,typeof v.keyName=="string")u[v.keyName]=v;else if(v.className!=null&&(r[v.className]=v),v.tagName!=null){Array.isArray(v.tagName)?v.tagName=v.tagName.map(function(y){return y.toUpperCase()}):v.tagName=v.tagName.toUpperCase();var C=Array.isArray(v.tagName)?v.tagName:[v.tagName];C.forEach(function(y){(f[y]==null||v.className==null)&&(f[y]=v)})}return v}h.register=c},function(e,h,m){var g=m(51),a=m(11),u=m(3),r=m(20),f=String.fromCharCode(0),l=function(n){Array.isArray(n)?this.ops=n:n!=null&&Array.isArray(n.ops)?this.ops=n.ops:this.ops=[]};l.prototype.insert=function(n,i){var o={};return n.length===0?this:(o.insert=n,i!=null&&typeof i=="object"&&Object.keys(i).length>0&&(o.attributes=i),this.push(o))},l.prototype.delete=function(n){return n<=0?this:this.push({delete:n})},l.prototype.retain=function(n,i){if(n<=0)return this;var o={retain:n};return i!=null&&typeof i=="object"&&Object.keys(i).length>0&&(o.attributes=i),this.push(o)},l.prototype.push=function(n){var i=this.ops.length,o=this.ops[i-1];if(n=u(!0,{},n),typeof o=="object"){if(typeof n.delete=="number"&&typeof o.delete=="number")return this.ops[i-1]={delete:o.delete+n.delete},this;if(typeof o.delete=="number"&&n.insert!=null&&(i-=1,o=this.ops[i-1],typeof o!="object"))return this.ops.unshift(n),this;if(a(n.attributes,o.attributes)){if(typeof n.insert=="string"&&typeof o.insert=="string")return this.ops[i-1]={insert:o.insert+n.insert},typeof n.attributes=="object"&&(this.ops[i-1].attributes=n.attributes),this;if(typeof n.retain=="number"&&typeof o.retain=="number")return this.ops[i-1]={retain:o.retain+n.retain},typeof n.attributes=="object"&&(this.ops[i-1].attributes=n.attributes),this}}return i===this.ops.length?this.ops.push(n):this.ops.splice(i,0,n),this},l.prototype.chop=function(){var n=this.ops[this.ops.length-1];return n&&n.retain&&!n.attributes&&this.ops.pop(),this},l.prototype.filter=function(n){return this.ops.filter(n)},l.prototype.forEach=function(n){this.ops.forEach(n)},l.prototype.map=function(n){return this.ops.map(n)},l.prototype.partition=function(n){var i=[],o=[];return this.forEach(function(s){var c=n(s)?i:o;c.push(s)}),[i,o]},l.prototype.reduce=function(n,i){return this.ops.reduce(n,i)},l.prototype.changeLength=function(){return this.reduce(function(n,i){return i.insert?n+r.length(i):i.delete?n-i.delete:n},0)},l.prototype.length=function(){return this.reduce(function(n,i){return n+r.length(i)},0)},l.prototype.slice=function(n,i){n=n||0,typeof i!="number"&&(i=1/0);for(var o=[],s=r.iterator(this.ops),c=0;c0&&o.next(c.retain-p)}for(var $=new l(s);i.hasNext()||o.hasNext();)if(o.peekType()==="insert")$.push(o.next());else if(i.peekType()==="delete")$.push(i.next());else{var v=Math.min(i.peekLength(),o.peekLength()),C=i.next(v),y=o.next(v);if(typeof y.retain=="number"){var _={};typeof C.retain=="number"?_.retain=v:_.insert=C.insert;var b=r.attributes.compose(C.attributes,y.attributes,typeof C.retain=="number");if(b&&(_.attributes=b),$.push(_),!o.hasNext()&&a($.ops[$.ops.length-1],_)){var E=new l(i.rest());return $.concat(E).chop()}}else typeof y.delete=="number"&&typeof C.retain=="number"&&$.push(y)}return $.chop()},l.prototype.concat=function(n){var i=new l(this.ops.slice());return n.ops.length>0&&(i.push(n.ops[0]),i.ops=i.ops.concat(n.ops.slice(1))),i},l.prototype.diff=function(n,i){if(this.ops===n.ops)return new l;var o=[this,n].map(function(v){return v.map(function(C){if(C.insert!=null)return typeof C.insert=="string"?C.insert:f;var y=v===n?"on":"with";throw new Error("diff() called "+y+" non-document")}).join("")}),s=new l,c=g(o[0],o[1],i),p=r.iterator(this.ops),$=r.iterator(n.ops);return c.forEach(function(v){for(var C=v[1].length;C>0;){var y=0;switch(v[0]){case g.INSERT:y=Math.min($.peekLength(),C),s.push($.next(y));break;case g.DELETE:y=Math.min(C,p.peekLength()),p.next(y),s.delete(y);break;case g.EQUAL:y=Math.min(p.peekLength(),$.peekLength(),C);var _=p.next(y),b=$.next(y);a(_.insert,b.insert)?s.retain(y,r.attributes.diff(_.attributes,b.attributes)):s.push(b).delete(y);break}C-=y}}),s.chop()},l.prototype.eachLine=function(n,i){i=i||` +`;for(var o=r.iterator(this.ops),s=new l,c=0;o.hasNext();){if(o.peekType()!=="insert")return;var p=o.peek(),$=r.length(p)-o.peekLength(),v=typeof p.insert=="string"?p.insert.indexOf(i,$)-$:-1;if(v<0)s.push(o.next());else if(v>0)s.push(o.next(v));else{if(n(s,o.next(1).attributes||{},c)===!1)return;c+=1,s=new l}}s.length()>0&&n(s,{},c)},l.prototype.transform=function(n,i){if(i=!!i,typeof n=="number")return this.transformPosition(n,i);for(var o=r.iterator(this.ops),s=r.iterator(n.ops),c=new l;o.hasNext()||s.hasNext();)if(o.peekType()==="insert"&&(i||s.peekType()!=="insert"))c.retain(r.length(o.next()));else if(s.peekType()==="insert")c.push(s.next());else{var p=Math.min(o.peekLength(),s.peekLength()),$=o.next(p),v=s.next(p);if($.delete)continue;v.delete?c.push(v):c.retain(p,r.attributes.transform($.attributes,v.attributes,i))}return c.chop()},l.prototype.transformPosition=function(n,i){i=!!i;for(var o=r.iterator(this.ops),s=0;o.hasNext()&&s<=n;){var c=o.peekLength(),p=o.peekType();if(o.next(),p==="delete"){n-=Math.min(c,n-s);continue}else p==="insert"&&(s0&&(w1&&arguments[1]!==void 0?arguments[1]:!1;if(L&&(w===0||w>=this.length()-E)){var q=this.clone();return w===0?(this.parent.insertBefore(q,this),this):(this.parent.insertBefore(q,this.next),q)}else{var A=a(T.prototype.__proto__||Object.getPrototypeOf(T.prototype),"split",this).call(this,w,L);return this.cache={},A}}}]),T}(i.default.Block);O.blotName="block",O.tagName="P",O.defaultChild="break",O.allowedChildren=[p.default,i.default.Embed,v.default];function M(k){var T=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{};return k==null||(typeof k.formats=="function"&&(T=(0,r.default)(T,k.formats())),k.parent==null||k.parent.blotName=="scroll"||k.parent.statics.scope!==k.statics.scope)?T:M(k.parent,T)}h.bubbleFormats=M,h.BlockEmbed=x,h.default=O},function(e,h,m){Object.defineProperty(h,"__esModule",{value:!0}),h.default=h.overload=h.expandConfig=void 0;var g=typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?function(F){return typeof F}:function(F){return F&&typeof Symbol=="function"&&F.constructor===Symbol&&F!==Symbol.prototype?"symbol":typeof F},a=function(){function F(V,R){var B=[],N=!0,P=!1,j=void 0;try{for(var D=V[Symbol.iterator](),W;!(N=(W=D.next()).done)&&(B.push(W.value),!(R&&B.length===R));N=!0);}catch(H){P=!0,j=H}finally{try{!N&&D.return&&D.return()}finally{if(P)throw j}}return B}return function(V,R){if(Array.isArray(V))return V;if(Symbol.iterator in Object(V))return F(V,R);throw new TypeError("Invalid attempt to destructure non-iterable instance")}}(),u=function(){function F(V,R){for(var B=0;B2&&arguments[2]!==void 0?arguments[2]:!1;if(typeof R!="string"){var j=R.attrName||R.blotName;typeof j=="string"?this.register("formats/"+j,R,B):Object.keys(R).forEach(function(D){N.register(D,R[D],B)})}else this.imports[R]!=null&&!P&&S.warn("Overwriting "+R+" with",B),this.imports[R]=B,(R.startsWith("blots/")||R.startsWith("formats/"))&&B.blotName!=="abstract"?$.default.register(B):R.startsWith("modules")&&typeof B.register=="function"&&B.register()}}]);function F(V){var R=this,B=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{};if(T(this,F),this.options=L(V,B),this.container=this.options.container,this.container==null)return S.error("Invalid Quill container",V);this.options.debug&&F.debug(this.options.debug);var N=this.container.innerHTML.trim();this.container.classList.add("ql-container"),this.container.innerHTML="",this.container.__quill=this,this.root=this.addContainer("ql-editor"),this.root.classList.add("ql-blank"),this.root.setAttribute("data-gramm",!1),this.scrollingContainer=this.options.scrollingContainer||this.root,this.emitter=new o.default,this.scroll=$.default.create(this.root,{emitter:this.emitter,whitelist:this.options.formats}),this.editor=new n.default(this.scroll),this.selection=new C.default(this.scroll,this.emitter),this.theme=new this.options.theme(this,this.options),this.keyboard=this.theme.addModule("keyboard"),this.clipboard=this.theme.addModule("clipboard"),this.history=this.theme.addModule("history"),this.theme.init(),this.emitter.on(o.default.events.EDITOR_CHANGE,function(j){j===o.default.events.TEXT_CHANGE&&R.root.classList.toggle("ql-blank",R.editor.isBlank())}),this.emitter.on(o.default.events.SCROLL_UPDATE,function(j,D){var W=R.selection.lastRange,H=W&&W.length===0?W.index:void 0;q.call(R,function(){return R.editor.update(null,D,H)},j)});var P=this.clipboard.convert(`
`+N+"


");this.setContents(P),this.history.clear(),this.options.placeholder&&this.root.setAttribute("data-placeholder",this.options.placeholder),this.options.readOnly&&this.disable()}return u(F,[{key:"addContainer",value:function(R){var B=arguments.length>1&&arguments[1]!==void 0?arguments[1]:null;if(typeof R=="string"){var N=R;R=document.createElement("div"),R.classList.add(N)}return this.container.insertBefore(R,B),R}},{key:"blur",value:function(){this.selection.setRange(null)}},{key:"deleteText",value:function(R,B,N){var P=this,j=A(R,B,N),D=a(j,4);return R=D[0],B=D[1],N=D[3],q.call(this,function(){return P.editor.deleteText(R,B)},N,R,-1*B)}},{key:"disable",value:function(){this.enable(!1)}},{key:"enable",value:function(){var R=arguments.length>0&&arguments[0]!==void 0?arguments[0]:!0;this.scroll.enable(R),this.container.classList.toggle("ql-disabled",!R)}},{key:"focus",value:function(){var R=this.scrollingContainer.scrollTop;this.selection.focus(),this.scrollingContainer.scrollTop=R,this.scrollIntoView()}},{key:"format",value:function(R,B){var N=this,P=arguments.length>2&&arguments[2]!==void 0?arguments[2]:o.default.sources.API;return q.call(this,function(){var j=N.getSelection(!0),D=new f.default;if(j==null)return D;if($.default.query(R,$.default.Scope.BLOCK))D=N.editor.formatLine(j.index,j.length,k({},R,B));else{if(j.length===0)return N.selection.format(R,B),D;D=N.editor.formatText(j.index,j.length,k({},R,B))}return N.setSelection(j,o.default.sources.SILENT),D},P)}},{key:"formatLine",value:function(R,B,N,P,j){var D=this,W=void 0,H=A(R,B,N,P,j),z=a(H,4);return R=z[0],B=z[1],W=z[2],j=z[3],q.call(this,function(){return D.editor.formatLine(R,B,W)},j,R,0)}},{key:"formatText",value:function(R,B,N,P,j){var D=this,W=void 0,H=A(R,B,N,P,j),z=a(H,4);return R=z[0],B=z[1],W=z[2],j=z[3],q.call(this,function(){return D.editor.formatText(R,B,W)},j,R,0)}},{key:"getBounds",value:function(R){var B=arguments.length>1&&arguments[1]!==void 0?arguments[1]:0,N=void 0;typeof R=="number"?N=this.selection.getBounds(R,B):N=this.selection.getBounds(R.index,R.length);var P=this.container.getBoundingClientRect();return{bottom:N.bottom-P.top,height:N.height,left:N.left-P.left,right:N.right-P.left,top:N.top-P.top,width:N.width}}},{key:"getContents",value:function(){var R=arguments.length>0&&arguments[0]!==void 0?arguments[0]:0,B=arguments.length>1&&arguments[1]!==void 0?arguments[1]:this.getLength()-R,N=A(R,B),P=a(N,2);return R=P[0],B=P[1],this.editor.getContents(R,B)}},{key:"getFormat",value:function(){var R=arguments.length>0&&arguments[0]!==void 0?arguments[0]:this.getSelection(!0),B=arguments.length>1&&arguments[1]!==void 0?arguments[1]:0;return typeof R=="number"?this.editor.getFormat(R,B):this.editor.getFormat(R.index,R.length)}},{key:"getIndex",value:function(R){return R.offset(this.scroll)}},{key:"getLength",value:function(){return this.scroll.length()}},{key:"getLeaf",value:function(R){return this.scroll.leaf(R)}},{key:"getLine",value:function(R){return this.scroll.line(R)}},{key:"getLines",value:function(){var R=arguments.length>0&&arguments[0]!==void 0?arguments[0]:0,B=arguments.length>1&&arguments[1]!==void 0?arguments[1]:Number.MAX_VALUE;return typeof R!="number"?this.scroll.lines(R.index,R.length):this.scroll.lines(R,B)}},{key:"getModule",value:function(R){return this.theme.modules[R]}},{key:"getSelection",value:function(){var R=arguments.length>0&&arguments[0]!==void 0?arguments[0]:!1;return R&&this.focus(),this.update(),this.selection.getRange()[0]}},{key:"getText",value:function(){var R=arguments.length>0&&arguments[0]!==void 0?arguments[0]:0,B=arguments.length>1&&arguments[1]!==void 0?arguments[1]:this.getLength()-R,N=A(R,B),P=a(N,2);return R=P[0],B=P[1],this.editor.getText(R,B)}},{key:"hasFocus",value:function(){return this.selection.hasFocus()}},{key:"insertEmbed",value:function(R,B,N){var P=this,j=arguments.length>3&&arguments[3]!==void 0?arguments[3]:F.sources.API;return q.call(this,function(){return P.editor.insertEmbed(R,B,N)},j,R)}},{key:"insertText",value:function(R,B,N,P,j){var D=this,W=void 0,H=A(R,0,N,P,j),z=a(H,4);return R=z[0],W=z[2],j=z[3],q.call(this,function(){return D.editor.insertText(R,B,W)},j,R,B.length)}},{key:"isEnabled",value:function(){return!this.container.classList.contains("ql-disabled")}},{key:"off",value:function(){return this.emitter.off.apply(this.emitter,arguments)}},{key:"on",value:function(){return this.emitter.on.apply(this.emitter,arguments)}},{key:"once",value:function(){return this.emitter.once.apply(this.emitter,arguments)}},{key:"pasteHTML",value:function(R,B,N){this.clipboard.dangerouslyPasteHTML(R,B,N)}},{key:"removeFormat",value:function(R,B,N){var P=this,j=A(R,B,N),D=a(j,4);return R=D[0],B=D[1],N=D[3],q.call(this,function(){return P.editor.removeFormat(R,B)},N,R)}},{key:"scrollIntoView",value:function(){this.selection.scrollIntoView(this.scrollingContainer)}},{key:"setContents",value:function(R){var B=this,N=arguments.length>1&&arguments[1]!==void 0?arguments[1]:o.default.sources.API;return q.call(this,function(){R=new f.default(R);var P=B.getLength(),j=B.editor.deleteText(0,P),D=B.editor.applyDelta(R),W=D.ops[D.ops.length-1];W!=null&&typeof W.insert=="string"&&W.insert[W.insert.length-1]===` +`&&(B.editor.deleteText(B.getLength()-1,1),D.delete(1));var H=j.compose(D);return H},N)}},{key:"setSelection",value:function(R,B,N){if(R==null)this.selection.setRange(null,B||F.sources.API);else{var P=A(R,B,N),j=a(P,4);R=j[0],B=j[1],N=j[3],this.selection.setRange(new v.Range(R,B),N),N!==o.default.sources.SILENT&&this.selection.scrollIntoView(this.scrollingContainer)}}},{key:"setText",value:function(R){var B=arguments.length>1&&arguments[1]!==void 0?arguments[1]:o.default.sources.API,N=new f.default().insert(R);return this.setContents(N,B)}},{key:"update",value:function(){var R=arguments.length>0&&arguments[0]!==void 0?arguments[0]:o.default.sources.USER,B=this.scroll.update(R);return this.selection.update(R),B}},{key:"updateContents",value:function(R){var B=this,N=arguments.length>1&&arguments[1]!==void 0?arguments[1]:o.default.sources.API;return q.call(this,function(){return R=new f.default(R),B.editor.applyDelta(R,N)},N,!0)}}]),F}();w.DEFAULTS={bounds:null,formats:null,modules:{},placeholder:"",readOnly:!1,scrollingContainer:null,strict:!0,theme:"default"},w.events=o.default.events,w.sources=o.default.sources,w.version="1.3.7",w.imports={delta:f.default,parchment:$.default,"core/module":c.default,"core/theme":O.default};function L(F,V){if(V=(0,_.default)(!0,{container:F,modules:{clipboard:!0,keyboard:!0,history:!0}},V),!V.theme||V.theme===w.DEFAULTS.theme)V.theme=O.default;else if(V.theme=w.import("themes/"+V.theme),V.theme==null)throw new Error("Invalid theme "+V.theme+". Did you register it?");var R=(0,_.default)(!0,{},V.theme.DEFAULTS);[R,V].forEach(function(P){P.modules=P.modules||{},Object.keys(P.modules).forEach(function(j){P.modules[j]===!0&&(P.modules[j]={})})});var B=Object.keys(R.modules).concat(Object.keys(V.modules)),N=B.reduce(function(P,j){var D=w.import("modules/"+j);return D==null?S.error("Cannot load "+j+" module. Are you sure you registered it?"):P[j]=D.DEFAULTS||{},P},{});return V.modules!=null&&V.modules.toolbar&&V.modules.toolbar.constructor!==Object&&(V.modules.toolbar={container:V.modules.toolbar}),V=(0,_.default)(!0,{},w.DEFAULTS,{modules:N},R,V),["bounds","container","scrollingContainer"].forEach(function(P){typeof V[P]=="string"&&(V[P]=document.querySelector(V[P]))}),V.modules=Object.keys(V.modules).reduce(function(P,j){return V.modules[j]&&(P[j]=V.modules[j]),P},{}),V}function q(F,V,R,B){if(this.options.strict&&!this.isEnabled()&&V===o.default.sources.USER)return new f.default;var N=R==null?null:this.getSelection(),P=this.editor.delta,j=F();if(N!=null&&(R===!0&&(R=N.index),B==null?N=I(N,j,V):B!==0&&(N=I(N,R,B,V)),this.setSelection(N,o.default.sources.SILENT)),j.length()>0){var D,W=[o.default.events.TEXT_CHANGE,j,P,V];if((D=this.emitter).emit.apply(D,[o.default.events.EDITOR_CHANGE].concat(W)),V!==o.default.sources.SILENT){var H;(H=this.emitter).emit.apply(H,W)}}return j}function A(F,V,R,B,N){var P={};return typeof F.index=="number"&&typeof F.length=="number"?typeof V!="number"?(N=B,B=R,R=V,V=F.length,F=F.index):(V=F.length,F=F.index):typeof V!="number"&&(N=B,B=R,R=V,V=0),(typeof R=="undefined"?"undefined":g(R))==="object"?(P=R,N=B):typeof R=="string"&&(B!=null?P[R]=B:N=R),N=N||o.default.sources.API,[F,V,P,N]}function I(F,V,R,B){if(F==null)return null;var N=void 0,P=void 0;if(V instanceof f.default){var j=[F.index,F.index+F.length].map(function(z){return V.transformPosition(z,B!==o.default.sources.USER)}),D=a(j,2);N=D[0],P=D[1]}else{var W=[F.index,F.index+F.length].map(function(z){return z=0?z+R:Math.max(V,z+R)}),H=a(W,2);N=H[0],P=H[1]}return new v.Range(N,P-N)}h.expandConfig=L,h.overload=A,h.default=w},function(e,h,m){Object.defineProperty(h,"__esModule",{value:!0});var g=function(){function p($,v){for(var C=0;C0){var y=this.parent.isolate(this.offset(),this.length());this.moveChildren(y),y.wrap(this)}}}],[{key:"compare",value:function(C,y){var _=$.order.indexOf(C),b=$.order.indexOf(y);return _>=0||b>=0?_-b:C===y?0:C1?b-1:0),x=1;x1&&arguments[1]!==void 0?arguments[1]:{};g(this,u),this.quill=r,this.options=f};a.DEFAULTS={},h.default=a},function(e,h,m){Object.defineProperty(h,"__esModule",{value:!0});var g=["error","warn","log","info"],a="warn";function u(f){if(g.indexOf(f)<=g.indexOf(a)){for(var l,n=arguments.length,i=Array(n>1?n-1:0),o=1;o0&&typeof i[0]!="number")}function n(i,o,s){var c,p;if(f(i)||f(o)||i.prototype!==o.prototype)return!1;if(u(i))return u(o)?(i=g.call(i),o=g.call(o),r(i,o,s)):!1;if(l(i)){if(!l(o)||i.length!==o.length)return!1;for(c=0;c=0;c--)if($[c]!=v[c])return!1;for(c=$.length-1;c>=0;c--)if(p=$[c],!r(i[p],o[p],s))return!1;return typeof i==typeof o}},function(e,h,m){Object.defineProperty(h,"__esModule",{value:!0});var g=m(1),a=function(){function u(r,f,l){l===void 0&&(l={}),this.attrName=r,this.keyName=f;var n=g.Scope.TYPE&g.Scope.ATTRIBUTE;l.scope!=null?this.scope=l.scope&g.Scope.LEVEL|n:this.scope=g.Scope.ATTRIBUTE,l.whitelist!=null&&(this.whitelist=l.whitelist)}return u.keys=function(r){return[].map.call(r.attributes,function(f){return f.name})},u.prototype.add=function(r,f){return this.canAdd(r,f)?(r.setAttribute(this.keyName,f),!0):!1},u.prototype.canAdd=function(r,f){var l=g.query(r,g.Scope.BLOT&(this.scope|g.Scope.TYPE));return l==null?!1:this.whitelist==null?!0:typeof f=="string"?this.whitelist.indexOf(f.replace(/["']/g,""))>-1:this.whitelist.indexOf(f)>-1},u.prototype.remove=function(r){r.removeAttribute(this.keyName)},u.prototype.value=function(r){var f=r.getAttribute(this.keyName);return this.canAdd(r,f)&&f?f:""},u}();h.default=a},function(e,h,m){Object.defineProperty(h,"__esModule",{value:!0}),h.default=h.Code=void 0;var g=function(){function x(O,M){var k=[],T=!0,S=!1,w=void 0;try{for(var L=O[Symbol.iterator](),q;!(T=(q=L.next()).done)&&(k.push(q.value),!(M&&k.length===M));T=!0);}catch(A){S=!0,w=A}finally{try{!T&&L.return&&L.return()}finally{if(S)throw w}}return k}return function(O,M){if(Array.isArray(O))return O;if(Symbol.iterator in Object(O))return x(O,M);throw new TypeError("Invalid attempt to destructure non-iterable instance")}}(),a=function(){function x(O,M){for(var k=0;k=k+T)){var q=this.newlineIndex(k,!0)+1,A=L-q+1,I=this.isolate(q,A),F=I.next;I.format(S,w),F instanceof O&&F.formatAt(0,k-q+T-A,S,w)}}}},{key:"insertAt",value:function(k,T,S){if(S==null){var w=this.descendant($.default,k),L=g(w,2),q=L[0],A=L[1];q.insertAt(A,T)}}},{key:"length",value:function(){var k=this.domNode.textContent.length;return this.domNode.textContent.endsWith(` +`)?k:k+1}},{key:"newlineIndex",value:function(k){var T=arguments.length>1&&arguments[1]!==void 0?arguments[1]:!1;if(T)return this.domNode.textContent.slice(0,k).lastIndexOf(` +`);var S=this.domNode.textContent.slice(k).indexOf(` +`);return S>-1?k+S:-1}},{key:"optimize",value:function(k){this.domNode.textContent.endsWith(` +`)||this.appendChild(n.default.create("text",` +`)),u(O.prototype.__proto__||Object.getPrototypeOf(O.prototype),"optimize",this).call(this,k);var T=this.next;T!=null&&T.prev===this&&T.statics.blotName===this.statics.blotName&&this.statics.formats(this.domNode)===T.statics.formats(T.domNode)&&(T.optimize(k),T.moveChildren(this),T.remove())}},{key:"replace",value:function(k){u(O.prototype.__proto__||Object.getPrototypeOf(O.prototype),"replace",this).call(this,k),[].slice.call(this.domNode.querySelectorAll("*")).forEach(function(T){var S=n.default.find(T);S==null?T.parentNode.removeChild(T):S instanceof n.default.Embed?S.remove():S.unwrap()})}}],[{key:"create",value:function(k){var T=u(O.__proto__||Object.getPrototypeOf(O),"create",this).call(this,k);return T.setAttribute("spellcheck",!1),T}},{key:"formats",value:function(){return!0}}]),O}(o.default);E.blotName="code-block",E.tagName="PRE",E.TAB=" ",h.Code=b,h.default=E},function(e,h,m){Object.defineProperty(h,"__esModule",{value:!0});var g=typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?function(F){return typeof F}:function(F){return F&&typeof Symbol=="function"&&F.constructor===Symbol&&F!==Symbol.prototype?"symbol":typeof F},a=function(){function F(V,R){var B=[],N=!0,P=!1,j=void 0;try{for(var D=V[Symbol.iterator](),W;!(N=(W=D.next()).done)&&(B.push(W.value),!(R&&B.length===R));N=!0);}catch(H){P=!0,j=H}finally{try{!N&&D.return&&D.return()}finally{if(P)throw j}}return B}return function(V,R){if(Array.isArray(V))return V;if(Symbol.iterator in Object(V))return F(V,R);throw new TypeError("Invalid attempt to destructure non-iterable instance")}}(),u=function(){function F(V,R){for(var B=0;B=P&&!z.endsWith(` +`)&&(N=!0),B.scroll.insertAt(j,z);var K=B.scroll.line(j),Z=a(K,2),ie=Z[0],se=Z[1],ue=(0,k.default)({},(0,v.bubbleFormats)(ie));if(ie instanceof C.default){var fe=ie.descendant(o.default.Leaf,se),ye=a(fe,1),_e=ye[0];ue=(0,k.default)(ue,(0,v.bubbleFormats)(_e))}H=n.default.attributes.diff(ue,H)||{}}else if(g(D.insert)==="object"){var J=Object.keys(D.insert)[0];if(J==null)return j;B.scroll.insertAt(j,J,D.insert[J])}P+=W}return Object.keys(H).forEach(function(Q){B.scroll.formatAt(j,W,Q,H[Q])}),j+W},0),R.reduce(function(j,D){return typeof D.delete=="number"?(B.scroll.deleteAt(j,D.delete),j):j+(D.retain||D.insert.length||1)},0),this.scroll.batchEnd(),this.update(R)}},{key:"deleteText",value:function(R,B){return this.scroll.deleteAt(R,B),this.update(new f.default().retain(R).delete(B))}},{key:"formatLine",value:function(R,B){var N=this,P=arguments.length>2&&arguments[2]!==void 0?arguments[2]:{};return this.scroll.update(),Object.keys(P).forEach(function(j){if(!(N.scroll.whitelist!=null&&!N.scroll.whitelist[j])){var D=N.scroll.lines(R,Math.max(B,1)),W=B;D.forEach(function(H){var z=H.length();if(!(H instanceof c.default))H.format(j,P[j]);else{var K=R-H.offset(N.scroll),Z=H.newlineIndex(K+W)-K+1;H.formatAt(K,Z,j,P[j])}W-=z})}}),this.scroll.optimize(),this.update(new f.default().retain(R).retain(B,(0,E.default)(P)))}},{key:"formatText",value:function(R,B){var N=this,P=arguments.length>2&&arguments[2]!==void 0?arguments[2]:{};return Object.keys(P).forEach(function(j){N.scroll.formatAt(R,B,j,P[j])}),this.update(new f.default().retain(R).retain(B,(0,E.default)(P)))}},{key:"getContents",value:function(R,B){return this.delta.slice(R,R+B)}},{key:"getDelta",value:function(){return this.scroll.lines().reduce(function(R,B){return R.concat(B.delta())},new f.default)}},{key:"getFormat",value:function(R){var B=arguments.length>1&&arguments[1]!==void 0?arguments[1]:0,N=[],P=[];B===0?this.scroll.path(R).forEach(function(D){var W=a(D,1),H=W[0];H instanceof C.default?N.push(H):H instanceof o.default.Leaf&&P.push(H)}):(N=this.scroll.lines(R,B),P=this.scroll.descendants(o.default.Leaf,R,B));var j=[N,P].map(function(D){if(D.length===0)return{};for(var W=(0,v.bubbleFormats)(D.shift());Object.keys(W).length>0;){var H=D.shift();if(H==null)return W;W=A((0,v.bubbleFormats)(H),W)}return W});return k.default.apply(k.default,j)}},{key:"getText",value:function(R,B){return this.getContents(R,B).filter(function(N){return typeof N.insert=="string"}).map(function(N){return N.insert}).join("")}},{key:"insertEmbed",value:function(R,B,N){return this.scroll.insertAt(R,B,N),this.update(new f.default().retain(R).insert(S({},B,N)))}},{key:"insertText",value:function(R,B){var N=this,P=arguments.length>2&&arguments[2]!==void 0?arguments[2]:{};return B=B.replace(/\r\n/g,` +`).replace(/\r/g,` +`),this.scroll.insertAt(R,B),Object.keys(P).forEach(function(j){N.scroll.formatAt(R,B.length,j,P[j])}),this.update(new f.default().retain(R).insert(B,(0,E.default)(P)))}},{key:"isBlank",value:function(){if(this.scroll.children.length==0)return!0;if(this.scroll.children.length>1)return!1;var R=this.scroll.children.head;return R.statics.blotName!==C.default.blotName||R.children.length>1?!1:R.children.head instanceof _.default}},{key:"removeFormat",value:function(R,B){var N=this.getText(R,B),P=this.scroll.line(R+B),j=a(P,2),D=j[0],W=j[1],H=0,z=new f.default;D!=null&&(D instanceof c.default?H=D.newlineIndex(W)-W+1:H=D.length()-W,z=D.delta().slice(W,W+H-1).insert(` +`));var K=this.getContents(R,B+H),Z=K.diff(new f.default().insert(N).concat(z)),ie=new f.default().retain(R).concat(Z);return this.applyDelta(ie)}},{key:"update",value:function(R){var B=arguments.length>1&&arguments[1]!==void 0?arguments[1]:[],N=arguments.length>2&&arguments[2]!==void 0?arguments[2]:void 0,P=this.delta;if(B.length===1&&B[0].type==="characterData"&&B[0].target.data.match(L)&&o.default.find(B[0].target)){var j=o.default.find(B[0].target),D=(0,v.bubbleFormats)(j),W=j.offset(this.scroll),H=B[0].oldValue.replace($.default.CONTENTS,""),z=new f.default().insert(H),K=new f.default().insert(j.value()),Z=new f.default().retain(W).concat(z.diff(K,N));R=Z.reduce(function(ie,se){return se.insert?ie.insert(se.insert,D):ie.push(se)},new f.default),this.delta=P.compose(R)}else this.delta=this.getDelta(),(!R||!(0,O.default)(P.compose(R),this.delta))&&(R=P.diff(this.delta,N));return R}}]),F}();function A(F,V){return Object.keys(V).reduce(function(R,B){return F[B]==null||(V[B]===F[B]?R[B]=V[B]:Array.isArray(V[B])?V[B].indexOf(F[B])<0&&(R[B]=V[B].concat([F[B]])):R[B]=[V[B],F[B]]),R},{})}function I(F){return F.reduce(function(V,R){if(R.insert===1){var B=(0,E.default)(R.attributes);return delete B.image,V.insert({image:R.attributes.image},B)}if(R.attributes!=null&&(R.attributes.list===!0||R.attributes.bullet===!0)&&(R=(0,E.default)(R),R.attributes.list?R.attributes.list="ordered":(R.attributes.list="bullet",delete R.attributes.bullet)),typeof R.insert=="string"){var N=R.insert.replace(/\r\n/g,` +`).replace(/\r/g,` +`);return V.insert(N,R.attributes)}return V.push(R)},new f.default)}h.default=q},function(e,h,m){Object.defineProperty(h,"__esModule",{value:!0}),h.default=h.Range=void 0;var g=function(){function x(O,M){var k=[],T=!0,S=!1,w=void 0;try{for(var L=O[Symbol.iterator](),q;!(T=(q=L.next()).done)&&(k.push(q.value),!(M&&k.length===M));T=!0);}catch(A){S=!0,w=A}finally{try{!T&&L.return&&L.return()}finally{if(S)throw w}}return k}return function(O,M){if(Array.isArray(O))return O;if(Symbol.iterator in Object(O))return x(O,M);throw new TypeError("Invalid attempt to destructure non-iterable instance")}}(),a=function(){function x(O,M){for(var k=0;k1&&arguments[1]!==void 0?arguments[1]:0;C(this,x),this.index=O,this.length=M},b=function(){function x(O,M){var k=this;C(this,x),this.emitter=M,this.scroll=O,this.composing=!1,this.mouseDown=!1,this.root=this.scroll.domNode,this.cursor=r.default.create("cursor",this),this.lastRange=this.savedRange=new _(0,0),this.handleComposition(),this.handleDragging(),this.emitter.listenDOM("selectionchange",document,function(){k.mouseDown||setTimeout(k.update.bind(k,s.default.sources.USER),1)}),this.emitter.on(s.default.events.EDITOR_CHANGE,function(T,S){T===s.default.events.TEXT_CHANGE&&S.length()>0&&k.update(s.default.sources.SILENT)}),this.emitter.on(s.default.events.SCROLL_BEFORE_UPDATE,function(){if(!!k.hasFocus()){var T=k.getNativeRange();T!=null&&T.start.node!==k.cursor.textNode&&k.emitter.once(s.default.events.SCROLL_UPDATE,function(){try{k.setNativeRange(T.start.node,T.start.offset,T.end.node,T.end.offset)}catch{}})}}),this.emitter.on(s.default.events.SCROLL_OPTIMIZE,function(T,S){if(S.range){var w=S.range,L=w.startNode,q=w.startOffset,A=w.endNode,I=w.endOffset;k.setNativeRange(L,q,A,I)}}),this.update(s.default.sources.SILENT)}return a(x,[{key:"handleComposition",value:function(){var M=this;this.root.addEventListener("compositionstart",function(){M.composing=!0}),this.root.addEventListener("compositionend",function(){if(M.composing=!1,M.cursor.parent){var k=M.cursor.restore();if(!k)return;setTimeout(function(){M.setNativeRange(k.startNode,k.startOffset,k.endNode,k.endOffset)},1)}})}},{key:"handleDragging",value:function(){var M=this;this.emitter.listenDOM("mousedown",document.body,function(){M.mouseDown=!0}),this.emitter.listenDOM("mouseup",document.body,function(){M.mouseDown=!1,M.update(s.default.sources.USER)})}},{key:"focus",value:function(){this.hasFocus()||(this.root.focus(),this.setRange(this.savedRange))}},{key:"format",value:function(M,k){if(!(this.scroll.whitelist!=null&&!this.scroll.whitelist[M])){this.scroll.update();var T=this.getNativeRange();if(!(T==null||!T.native.collapsed||r.default.query(M,r.default.Scope.BLOCK))){if(T.start.node!==this.cursor.textNode){var S=r.default.find(T.start.node,!1);if(S==null)return;if(S instanceof r.default.Leaf){var w=S.split(T.start.offset);S.parent.insertBefore(this.cursor,w)}else S.insertBefore(this.cursor,T.start.node);this.cursor.attach()}this.cursor.format(M,k),this.scroll.optimize(),this.setNativeRange(this.cursor.textNode,this.cursor.textNode.data.length),this.update()}}}},{key:"getBounds",value:function(M){var k=arguments.length>1&&arguments[1]!==void 0?arguments[1]:0,T=this.scroll.length();M=Math.min(M,T-1),k=Math.min(M+k,T-1)-M;var S=void 0,w=this.scroll.leaf(M),L=g(w,2),q=L[0],A=L[1];if(q==null)return null;var I=q.position(A,!0),F=g(I,2);S=F[0],A=F[1];var V=document.createRange();if(k>0){V.setStart(S,A);var R=this.scroll.leaf(M+k),B=g(R,2);if(q=B[0],A=B[1],q==null)return null;var N=q.position(A,!0),P=g(N,2);return S=P[0],A=P[1],V.setEnd(S,A),V.getBoundingClientRect()}else{var j="left",D=void 0;return S instanceof Text?(A0&&(j="right")),{bottom:D.top+D.height,height:D.height,left:D[j],right:D[j],top:D.top,width:0}}}},{key:"getNativeRange",value:function(){var M=document.getSelection();if(M==null||M.rangeCount<=0)return null;var k=M.getRangeAt(0);if(k==null)return null;var T=this.normalizeNative(k);return y.info("getNativeRange",T),T}},{key:"getRange",value:function(){var M=this.getNativeRange();if(M==null)return[null,null];var k=this.normalizedToRange(M);return[k,M]}},{key:"hasFocus",value:function(){return document.activeElement===this.root}},{key:"normalizedToRange",value:function(M){var k=this,T=[[M.start.node,M.start.offset]];M.native.collapsed||T.push([M.end.node,M.end.offset]);var S=T.map(function(q){var A=g(q,2),I=A[0],F=A[1],V=r.default.find(I,!0),R=V.offset(k.scroll);return F===0?R:V instanceof r.default.Container?R+V.length():R+V.index(I,F)}),w=Math.min(Math.max.apply(Math,v(S)),this.scroll.length()-1),L=Math.min.apply(Math,[w].concat(v(S)));return new _(L,w-L)}},{key:"normalizeNative",value:function(M){if(!E(this.root,M.startContainer)||!M.collapsed&&!E(this.root,M.endContainer))return null;var k={start:{node:M.startContainer,offset:M.startOffset},end:{node:M.endContainer,offset:M.endOffset},native:M};return[k.start,k.end].forEach(function(T){for(var S=T.node,w=T.offset;!(S instanceof Text)&&S.childNodes.length>0;)if(S.childNodes.length>w)S=S.childNodes[w],w=0;else if(S.childNodes.length===w)S=S.lastChild,w=S instanceof Text?S.data.length:S.childNodes.length+1;else break;T.node=S,T.offset=w}),k}},{key:"rangeToNative",value:function(M){var k=this,T=M.collapsed?[M.index]:[M.index,M.index+M.length],S=[],w=this.scroll.length();return T.forEach(function(L,q){L=Math.min(w-1,L);var A=void 0,I=k.scroll.leaf(L),F=g(I,2),V=F[0],R=F[1],B=V.position(R,q!==0),N=g(B,2);A=N[0],R=N[1],S.push(A,R)}),S.length<2&&(S=S.concat(S)),S}},{key:"scrollIntoView",value:function(M){var k=this.lastRange;if(k!=null){var T=this.getBounds(k.index,k.length);if(T!=null){var S=this.scroll.length()-1,w=this.scroll.line(Math.min(k.index,S)),L=g(w,1),q=L[0],A=q;if(k.length>0){var I=this.scroll.line(Math.min(k.index+k.length,S)),F=g(I,1);A=F[0]}if(!(q==null||A==null)){var V=M.getBoundingClientRect();T.topV.bottom&&(M.scrollTop+=T.bottom-V.bottom)}}}}},{key:"setNativeRange",value:function(M,k){var T=arguments.length>2&&arguments[2]!==void 0?arguments[2]:M,S=arguments.length>3&&arguments[3]!==void 0?arguments[3]:k,w=arguments.length>4&&arguments[4]!==void 0?arguments[4]:!1;if(y.info("setNativeRange",M,k,T,S),!(M!=null&&(this.root.parentNode==null||M.parentNode==null||T.parentNode==null))){var L=document.getSelection();if(L!=null)if(M!=null){this.hasFocus()||this.root.focus();var q=(this.getNativeRange()||{}).native;if(q==null||w||M!==q.startContainer||k!==q.startOffset||T!==q.endContainer||S!==q.endOffset){M.tagName=="BR"&&(k=[].indexOf.call(M.parentNode.childNodes,M),M=M.parentNode),T.tagName=="BR"&&(S=[].indexOf.call(T.parentNode.childNodes,T),T=T.parentNode);var A=document.createRange();A.setStart(M,k),A.setEnd(T,S),L.removeAllRanges(),L.addRange(A)}}else L.removeAllRanges(),this.root.blur(),document.body.focus()}}},{key:"setRange",value:function(M){var k=arguments.length>1&&arguments[1]!==void 0?arguments[1]:!1,T=arguments.length>2&&arguments[2]!==void 0?arguments[2]:s.default.sources.API;if(typeof k=="string"&&(T=k,k=!1),y.info("setRange",M),M!=null){var S=this.rangeToNative(M);this.setNativeRange.apply(this,v(S).concat([k]))}else this.setNativeRange(null);this.update(T)}},{key:"update",value:function(){var M=arguments.length>0&&arguments[0]!==void 0?arguments[0]:s.default.sources.USER,k=this.lastRange,T=this.getRange(),S=g(T,2),w=S[0],L=S[1];if(this.lastRange=w,this.lastRange!=null&&(this.savedRange=this.lastRange),!(0,i.default)(k,this.lastRange)){var q;!this.composing&&L!=null&&L.native.collapsed&&L.start.node!==this.cursor.textNode&&this.cursor.restore();var A=[s.default.events.SELECTION_CHANGE,(0,l.default)(this.lastRange),(0,l.default)(k),M];if((q=this.emitter).emit.apply(q,[s.default.events.EDITOR_CHANGE].concat(A)),M!==s.default.sources.SILENT){var I;(I=this.emitter).emit.apply(I,A)}}}}]),x}();function E(x,O){try{O.parentNode}catch{return!1}return O instanceof Text&&(O=O.parentNode),x.contains(O)}h.Range=_,h.default=b},function(e,h,m){Object.defineProperty(h,"__esModule",{value:!0});var g=function(){function s(c,p){for(var $=0;$0&&(o+=1),[this.parent.domNode,o]},l.prototype.value=function(){var n;return n={},n[this.statics.blotName]=this.statics.value(this.domNode)||!0,n},l.scope=u.Scope.INLINE_BLOT,l}(a.default);h.default=r},function(e,h,m){var g=m(11),a=m(3),u={attributes:{compose:function(f,l,n){typeof f!="object"&&(f={}),typeof l!="object"&&(l={});var i=a(!0,{},l);n||(i=Object.keys(i).reduce(function(s,c){return i[c]!=null&&(s[c]=i[c]),s},{}));for(var o in f)f[o]!==void 0&&l[o]===void 0&&(i[o]=f[o]);return Object.keys(i).length>0?i:void 0},diff:function(f,l){typeof f!="object"&&(f={}),typeof l!="object"&&(l={});var n=Object.keys(f).concat(Object.keys(l)).reduce(function(i,o){return g(f[o],l[o])||(i[o]=l[o]===void 0?null:l[o]),i},{});return Object.keys(n).length>0?n:void 0},transform:function(f,l,n){if(typeof f!="object")return l;if(typeof l=="object"){if(!n)return l;var i=Object.keys(l).reduce(function(o,s){return f[s]===void 0&&(o[s]=l[s]),o},{});return Object.keys(i).length>0?i:void 0}}},iterator:function(f){return new r(f)},length:function(f){return typeof f.delete=="number"?f.delete:typeof f.retain=="number"?f.retain:typeof f.insert=="string"?f.insert.length:1}};function r(f){this.ops=f,this.index=0,this.offset=0}r.prototype.hasNext=function(){return this.peekLength()<1/0},r.prototype.next=function(f){f||(f=1/0);var l=this.ops[this.index];if(l){var n=this.offset,i=u.length(l);if(f>=i-n?(f=i-n,this.index+=1,this.offset=0):this.offset+=f,typeof l.delete=="number")return{delete:f};var o={};return l.attributes&&(o.attributes=l.attributes),typeof l.retain=="number"?o.retain=f:typeof l.insert=="string"?o.insert=l.insert.substr(n,f):o.insert=l.insert,o}else return{retain:1/0}},r.prototype.peek=function(){return this.ops[this.index]},r.prototype.peekLength=function(){return this.ops[this.index]?u.length(this.ops[this.index])-this.offset:1/0},r.prototype.peekType=function(){return this.ops[this.index]?typeof this.ops[this.index].delete=="number"?"delete":typeof this.ops[this.index].retain=="number"?"retain":"insert":"retain"},r.prototype.rest=function(){if(this.hasNext()){if(this.offset===0)return this.ops.slice(this.index);var f=this.offset,l=this.index,n=this.next(),i=this.ops.slice(this.index);return this.offset=f,this.index=l,[n].concat(i)}else return[]},e.exports=u},function(e,h){var m=function(){function g(c,p){return p!=null&&c instanceof p}var a;try{a=Map}catch{a=function(){}}var u;try{u=Set}catch{u=function(){}}var r;try{r=Promise}catch{r=function(){}}function f(c,p,$,v,C){typeof p=="object"&&($=p.depth,v=p.prototype,C=p.includeNonEnumerable,p=p.circular);var y=[],_=[],b=typeof Buffer!="undefined";typeof p=="undefined"&&(p=!0),typeof $=="undefined"&&($=1/0);function E(x,O){if(x===null)return null;if(O===0)return x;var M,k;if(typeof x!="object")return x;if(g(x,a))M=new a;else if(g(x,u))M=new u;else if(g(x,r))M=new r(function(V,R){x.then(function(B){V(E(B,O-1))},function(B){R(E(B,O-1))})});else if(f.__isArray(x))M=[];else if(f.__isRegExp(x))M=new RegExp(x.source,s(x)),x.lastIndex&&(M.lastIndex=x.lastIndex);else if(f.__isDate(x))M=new Date(x.getTime());else{if(b&&Buffer.isBuffer(x))return Buffer.allocUnsafe?M=Buffer.allocUnsafe(x.length):M=new Buffer(x.length),x.copy(M),M;g(x,Error)?M=Object.create(x):typeof v=="undefined"?(k=Object.getPrototypeOf(x),M=Object.create(k)):(M=Object.create(v),k=v)}if(p){var T=y.indexOf(x);if(T!=-1)return _[T];y.push(x),_.push(M)}g(x,a)&&x.forEach(function(V,R){var B=E(R,O-1),N=E(V,O-1);M.set(B,N)}),g(x,u)&&x.forEach(function(V){var R=E(V,O-1);M.add(R)});for(var S in x){var w;k&&(w=Object.getOwnPropertyDescriptor(k,S)),!(w&&w.set==null)&&(M[S]=E(x[S],O-1))}if(Object.getOwnPropertySymbols)for(var L=Object.getOwnPropertySymbols(x),S=0;S0){if(A instanceof i.BlockEmbed||R instanceof i.BlockEmbed){this.optimize();return}if(A instanceof $.default){var B=A.newlineIndex(A.length(),!0);if(B>-1&&(A=A.split(B+1),A===R)){this.optimize();return}}else if(R instanceof $.default){var N=R.newlineIndex(0);N>-1&&R.split(N+1)}var P=R.children.head instanceof c.default?null:R.children.head;A.moveChildren(R,P),A.remove()}this.optimize()}},{key:"enable",value:function(){var S=arguments.length>0&&arguments[0]!==void 0?arguments[0]:!0;this.domNode.setAttribute("contenteditable",S)}},{key:"formatAt",value:function(S,w,L,q){this.whitelist!=null&&!this.whitelist[L]||(u(k.prototype.__proto__||Object.getPrototypeOf(k.prototype),"formatAt",this).call(this,S,w,L,q),this.optimize())}},{key:"insertAt",value:function(S,w,L){if(!(L!=null&&this.whitelist!=null&&!this.whitelist[w])){if(S>=this.length())if(L==null||f.default.query(w,f.default.Scope.BLOCK)==null){var q=f.default.create(this.statics.defaultChild);this.appendChild(q),L==null&&w.endsWith(` +`)&&(w=w.slice(0,-1)),q.insertAt(0,w,L)}else{var A=f.default.create(w,L);this.appendChild(A)}else u(k.prototype.__proto__||Object.getPrototypeOf(k.prototype),"insertAt",this).call(this,S,w,L);this.optimize()}}},{key:"insertBefore",value:function(S,w){if(S.statics.scope===f.default.Scope.INLINE_BLOT){var L=f.default.create(this.statics.defaultChild);L.appendChild(S),S=L}u(k.prototype.__proto__||Object.getPrototypeOf(k.prototype),"insertBefore",this).call(this,S,w)}},{key:"leaf",value:function(S){return this.path(S).pop()||[null,-1]}},{key:"line",value:function(S){return S===this.length()?this.line(S-1):this.descendant(x,S)}},{key:"lines",value:function(){var S=arguments.length>0&&arguments[0]!==void 0?arguments[0]:0,w=arguments.length>1&&arguments[1]!==void 0?arguments[1]:Number.MAX_VALUE,L=function q(A,I,F){var V=[],R=F;return A.children.forEachAt(I,F,function(B,N,P){x(B)?V.push(B):B instanceof f.default.Container&&(V=V.concat(q(B,N,R))),R-=P}),V};return L(this,S,w)}},{key:"optimize",value:function(){var S=arguments.length>0&&arguments[0]!==void 0?arguments[0]:[],w=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{};this.batch!==!0&&(u(k.prototype.__proto__||Object.getPrototypeOf(k.prototype),"optimize",this).call(this,S,w),S.length>0&&this.emitter.emit(n.default.events.SCROLL_OPTIMIZE,S,w))}},{key:"path",value:function(S){return u(k.prototype.__proto__||Object.getPrototypeOf(k.prototype),"path",this).call(this,S).slice(1)}},{key:"update",value:function(S){if(this.batch!==!0){var w=n.default.sources.USER;typeof S=="string"&&(w=S),Array.isArray(S)||(S=this.observer.takeRecords()),S.length>0&&this.emitter.emit(n.default.events.SCROLL_BEFORE_UPDATE,w,S),u(k.prototype.__proto__||Object.getPrototypeOf(k.prototype),"update",this).call(this,S.concat([])),S.length>0&&this.emitter.emit(n.default.events.SCROLL_UPDATE,w,S)}}}]),k}(f.default.Scroll);O.blotName="scroll",O.className="ql-editor",O.tagName="DIV",O.defaultChild="block",O.allowedChildren=[o.default,i.BlockEmbed,C.default],h.default=O},function(e,h,m){Object.defineProperty(h,"__esModule",{value:!0}),h.SHORTKEY=h.default=void 0;var g=typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?function(D){return typeof D}:function(D){return D&&typeof Symbol=="function"&&D.constructor===Symbol&&D!==Symbol.prototype?"symbol":typeof D},a=function(){function D(W,H){var z=[],K=!0,Z=!1,ie=void 0;try{for(var se=W[Symbol.iterator](),ue;!(K=(ue=se.next()).done)&&(z.push(ue.value),!(H&&z.length===H));K=!0);}catch(fe){Z=!0,ie=fe}finally{try{!K&&se.return&&se.return()}finally{if(Z)throw ie}}return z}return function(W,H){if(Array.isArray(W))return W;if(Symbol.iterator in Object(W))return D(W,H);throw new TypeError("Invalid attempt to destructure non-iterable instance")}}(),u=function(){function D(W,H){for(var z=0;z1&&arguments[1]!==void 0?arguments[1]:{},Z=arguments.length>2&&arguments[2]!==void 0?arguments[2]:{},ie=j(z);if(ie==null||ie.key==null)return L.warn("Attempted to add invalid keyboard binding",ie);typeof K=="function"&&(K={handler:K}),typeof Z=="function"&&(Z={handler:Z}),ie=(0,o.default)(ie,K,Z),this.bindings[ie.key]=this.bindings[ie.key]||[],this.bindings[ie.key].push(ie)}},{key:"listen",value:function(){var z=this;this.quill.root.addEventListener("keydown",function(K){if(!K.defaultPrevented){var Z=K.which||K.keyCode,ie=(z.bindings[Z]||[]).filter(function(U){return W.match(K,U)});if(ie.length!==0){var se=z.quill.getSelection();if(!(se==null||!z.quill.hasFocus())){var ue=z.quill.getLine(se.index),fe=a(ue,2),ye=fe[0],_e=fe[1],J=z.quill.getLeaf(se.index),Q=a(J,2),ne=Q[0],le=Q[1],te=se.length===0?[ne,le]:z.quill.getLeaf(se.index+se.length),me=a(te,2),$e=me[0],be=me[1],X=ne instanceof C.default.Text?ne.value().slice(0,le):"",ae=$e instanceof C.default.Text?$e.value().slice(be):"",oe={collapsed:se.length===0,empty:se.length===0&&ye.length()<=1,format:z.quill.getFormat(se),offset:_e,prefix:X,suffix:ae},G=ie.some(function(U){if(U.collapsed!=null&&U.collapsed!==oe.collapsed||U.empty!=null&&U.empty!==oe.empty||U.offset!=null&&U.offset!==oe.offset)return!1;if(Array.isArray(U.format)){if(U.format.every(function(Y){return oe.format[Y]==null}))return!1}else if(g(U.format)==="object"&&!Object.keys(U.format).every(function(Y){return U.format[Y]===!0?oe.format[Y]!=null:U.format[Y]===!1?oe.format[Y]==null:(0,n.default)(U.format[Y],oe.format[Y])}))return!1;return U.prefix!=null&&!U.prefix.test(oe.prefix)||U.suffix!=null&&!U.suffix.test(oe.suffix)?!1:U.handler.call(z,se,oe)!==!0});G&&K.preventDefault()}}}})}}]),W}(O.default);A.keys={BACKSPACE:8,TAB:9,ENTER:13,ESCAPE:27,LEFT:37,UP:38,RIGHT:39,DOWN:40,DELETE:46},A.DEFAULTS={bindings:{bold:P("bold"),italic:P("italic"),underline:P("underline"),indent:{key:A.keys.TAB,format:["blockquote","indent","list"],handler:function(W,H){if(H.collapsed&&H.offset!==0)return!0;this.quill.format("indent","+1",_.default.sources.USER)}},outdent:{key:A.keys.TAB,shiftKey:!0,format:["blockquote","indent","list"],handler:function(W,H){if(H.collapsed&&H.offset!==0)return!0;this.quill.format("indent","-1",_.default.sources.USER)}},"outdent backspace":{key:A.keys.BACKSPACE,collapsed:!0,shiftKey:null,metaKey:null,ctrlKey:null,altKey:null,format:["indent","list"],offset:0,handler:function(W,H){H.format.indent!=null?this.quill.format("indent","-1",_.default.sources.USER):H.format.list!=null&&this.quill.format("list",!1,_.default.sources.USER)}},"indent code-block":N(!0),"outdent code-block":N(!1),"remove tab":{key:A.keys.TAB,shiftKey:!0,collapsed:!0,prefix:/\t$/,handler:function(W){this.quill.deleteText(W.index-1,1,_.default.sources.USER)}},tab:{key:A.keys.TAB,handler:function(W){this.quill.history.cutoff();var H=new c.default().retain(W.index).delete(W.length).insert(" ");this.quill.updateContents(H,_.default.sources.USER),this.quill.history.cutoff(),this.quill.setSelection(W.index+1,_.default.sources.SILENT)}},"list empty enter":{key:A.keys.ENTER,collapsed:!0,format:["list"],empty:!0,handler:function(W,H){this.quill.format("list",!1,_.default.sources.USER),H.format.indent&&this.quill.format("indent",!1,_.default.sources.USER)}},"checklist enter":{key:A.keys.ENTER,collapsed:!0,format:{list:"checked"},handler:function(W){var H=this.quill.getLine(W.index),z=a(H,2),K=z[0],Z=z[1],ie=(0,o.default)({},K.formats(),{list:"checked"}),se=new c.default().retain(W.index).insert(` +`,ie).retain(K.length()-Z-1).retain(1,{list:"unchecked"});this.quill.updateContents(se,_.default.sources.USER),this.quill.setSelection(W.index+1,_.default.sources.SILENT),this.quill.scrollIntoView()}},"header enter":{key:A.keys.ENTER,collapsed:!0,format:["header"],suffix:/^$/,handler:function(W,H){var z=this.quill.getLine(W.index),K=a(z,2),Z=K[0],ie=K[1],se=new c.default().retain(W.index).insert(` +`,H.format).retain(Z.length()-ie-1).retain(1,{header:null});this.quill.updateContents(se,_.default.sources.USER),this.quill.setSelection(W.index+1,_.default.sources.SILENT),this.quill.scrollIntoView()}},"list autofill":{key:" ",collapsed:!0,format:{list:!1},prefix:/^\s*?(\d+\.|-|\*|\[ ?\]|\[x\])$/,handler:function(W,H){var z=H.prefix.length,K=this.quill.getLine(W.index),Z=a(K,2),ie=Z[0],se=Z[1];if(se>z)return!0;var ue=void 0;switch(H.prefix.trim()){case"[]":case"[ ]":ue="unchecked";break;case"[x]":ue="checked";break;case"-":case"*":ue="bullet";break;default:ue="ordered"}this.quill.insertText(W.index," ",_.default.sources.USER),this.quill.history.cutoff();var fe=new c.default().retain(W.index-se).delete(z+1).retain(ie.length()-2-se).retain(1,{list:ue});this.quill.updateContents(fe,_.default.sources.USER),this.quill.history.cutoff(),this.quill.setSelection(W.index-z,_.default.sources.SILENT)}},"code exit":{key:A.keys.ENTER,collapsed:!0,format:["code-block"],prefix:/\n\n$/,suffix:/^\s+$/,handler:function(W){var H=this.quill.getLine(W.index),z=a(H,2),K=z[0],Z=z[1],ie=new c.default().retain(W.index+K.length()-Z-2).retain(1,{"code-block":null}).delete(1);this.quill.updateContents(ie,_.default.sources.USER)}},"embed left":I(A.keys.LEFT,!1),"embed left shift":I(A.keys.LEFT,!0),"embed right":I(A.keys.RIGHT,!1),"embed right shift":I(A.keys.RIGHT,!0)}};function I(D,W){var H,z=D===A.keys.LEFT?"prefix":"suffix";return H={key:D,shiftKey:W,altKey:null},k(H,z,/^$/),k(H,"handler",function(Z){var ie=Z.index;D===A.keys.RIGHT&&(ie+=Z.length+1);var se=this.quill.getLeaf(ie),ue=a(se,1),fe=ue[0];return fe instanceof C.default.Embed?(D===A.keys.LEFT?W?this.quill.setSelection(Z.index-1,Z.length+1,_.default.sources.USER):this.quill.setSelection(Z.index-1,_.default.sources.USER):W?this.quill.setSelection(Z.index,Z.length+1,_.default.sources.USER):this.quill.setSelection(Z.index+Z.length+1,_.default.sources.USER),!1):!0}),H}function F(D,W){if(!(D.index===0||this.quill.getLength()<=1)){var H=this.quill.getLine(D.index),z=a(H,1),K=z[0],Z={};if(W.offset===0){var ie=this.quill.getLine(D.index-1),se=a(ie,1),ue=se[0];if(ue!=null&&ue.length()>1){var fe=K.formats(),ye=this.quill.getFormat(D.index-1,1);Z=$.default.attributes.diff(fe,ye)||{}}}var _e=/[\uD800-\uDBFF][\uDC00-\uDFFF]$/.test(W.prefix)?2:1;this.quill.deleteText(D.index-_e,_e,_.default.sources.USER),Object.keys(Z).length>0&&this.quill.formatLine(D.index-_e,_e,Z,_.default.sources.USER),this.quill.focus()}}function V(D,W){var H=/^[\uD800-\uDBFF][\uDC00-\uDFFF]/.test(W.suffix)?2:1;if(!(D.index>=this.quill.getLength()-H)){var z={},K=0,Z=this.quill.getLine(D.index),ie=a(Z,1),se=ie[0];if(W.offset>=se.length()-1){var ue=this.quill.getLine(D.index+1),fe=a(ue,1),ye=fe[0];if(ye){var _e=se.formats(),J=this.quill.getFormat(D.index,1);z=$.default.attributes.diff(_e,J)||{},K=ye.length()}}this.quill.deleteText(D.index,H,_.default.sources.USER),Object.keys(z).length>0&&this.quill.formatLine(D.index+K-1,H,z,_.default.sources.USER)}}function R(D){var W=this.quill.getLines(D),H={};if(W.length>1){var z=W[0].formats(),K=W[W.length-1].formats();H=$.default.attributes.diff(K,z)||{}}this.quill.deleteText(D,_.default.sources.USER),Object.keys(H).length>0&&this.quill.formatLine(D.index,1,H,_.default.sources.USER),this.quill.setSelection(D.index,_.default.sources.SILENT),this.quill.focus()}function B(D,W){var H=this;D.length>0&&this.quill.scroll.deleteAt(D.index,D.length);var z=Object.keys(W.format).reduce(function(K,Z){return C.default.query(Z,C.default.Scope.BLOCK)&&!Array.isArray(W.format[Z])&&(K[Z]=W.format[Z]),K},{});this.quill.insertText(D.index,` +`,z,_.default.sources.USER),this.quill.setSelection(D.index+1,_.default.sources.SILENT),this.quill.focus(),Object.keys(W.format).forEach(function(K){z[K]==null&&(Array.isArray(W.format[K])||K!=="link"&&H.quill.format(K,W.format[K],_.default.sources.USER))})}function N(D){return{key:A.keys.TAB,shiftKey:!D,format:{"code-block":!0},handler:function(H){var z=C.default.query("code-block"),K=H.index,Z=H.length,ie=this.quill.scroll.descendant(z,K),se=a(ie,2),ue=se[0],fe=se[1];if(ue!=null){var ye=this.quill.getIndex(ue),_e=ue.newlineIndex(fe,!0)+1,J=ue.newlineIndex(ye+fe+Z),Q=ue.domNode.textContent.slice(_e,J).split(` +`);fe=0,Q.forEach(function(ne,le){D?(ue.insertAt(_e+fe,z.TAB),fe+=z.TAB.length,le===0?K+=z.TAB.length:Z+=z.TAB.length):ne.startsWith(z.TAB)&&(ue.deleteAt(_e+fe,z.TAB.length),fe-=z.TAB.length,le===0?K-=z.TAB.length:Z-=z.TAB.length),fe+=ne.length+1}),this.quill.update(_.default.sources.USER),this.quill.setSelection(K,Z,_.default.sources.SILENT)}}}}function P(D){return{key:D[0].toUpperCase(),shortKey:!0,handler:function(H,z){this.quill.format(D,!z.format[D],_.default.sources.USER)}}}function j(D){if(typeof D=="string"||typeof D=="number")return j({key:D});if((typeof D=="undefined"?"undefined":g(D))==="object"&&(D=(0,f.default)(D,!1)),typeof D.key=="string")if(A.keys[D.key.toUpperCase()]!=null)D.key=A.keys[D.key.toUpperCase()];else if(D.key.length===1)D.key=D.key.toUpperCase().charCodeAt(0);else return null;return D.shortKey&&(D[q]=D.shortKey,delete D.shortKey),D}h.default=A,h.SHORTKEY=q},function(e,h,m){Object.defineProperty(h,"__esModule",{value:!0});var g=function(){function $(v,C){var y=[],_=!0,b=!1,E=void 0;try{for(var x=v[Symbol.iterator](),O;!(_=(O=x.next()).done)&&(y.push(O.value),!(C&&y.length===C));_=!0);}catch(M){b=!0,E=M}finally{try{!_&&x.return&&x.return()}finally{if(b)throw E}}return y}return function(v,C){if(Array.isArray(v))return v;if(Symbol.iterator in Object(v))return $(v,C);throw new TypeError("Invalid attempt to destructure non-iterable instance")}}(),a=function $(v,C,y){v===null&&(v=Function.prototype);var _=Object.getOwnPropertyDescriptor(v,C);if(_===void 0){var b=Object.getPrototypeOf(v);return b===null?void 0:$(b,C,y)}else{if("value"in _)return _.value;var E=_.get;return E===void 0?void 0:E.call(y)}},u=function(){function $(v,C){for(var y=0;y-1}h.default=o,h.sanitize=s},function(e,h,m){Object.defineProperty(h,"__esModule",{value:!0});var g=typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?function(p){return typeof p}:function(p){return p&&typeof Symbol=="function"&&p.constructor===Symbol&&p!==Symbol.prototype?"symbol":typeof p},a=function(){function p($,v){for(var C=0;C1&&arguments[1]!==void 0?arguments[1]:!1,y=this.container.querySelector(".ql-selected");if(v!==y&&(y!=null&&y.classList.remove("ql-selected"),v!=null&&(v.classList.add("ql-selected"),this.select.selectedIndex=[].indexOf.call(v.parentNode.children,v),v.hasAttribute("data-value")?this.label.setAttribute("data-value",v.getAttribute("data-value")):this.label.removeAttribute("data-value"),v.hasAttribute("data-label")?this.label.setAttribute("data-label",v.getAttribute("data-label")):this.label.removeAttribute("data-label"),C))){if(typeof Event=="function")this.select.dispatchEvent(new Event("change"));else if((typeof Event=="undefined"?"undefined":g(Event))==="object"){var _=document.createEvent("Event");_.initEvent("change",!0,!0),this.select.dispatchEvent(_)}this.close()}}},{key:"update",value:function(){var v=void 0;if(this.select.selectedIndex>-1){var C=this.container.querySelector(".ql-picker-options").children[this.select.selectedIndex];v=this.select.options[this.select.selectedIndex],this.selectItem(C)}else this.selectItem(null);var y=v!=null&&v!==this.select.querySelector("option[selected]");this.label.classList.toggle("ql-active",y)}}]),p}();h.default=c},function(e,h,m){Object.defineProperty(h,"__esModule",{value:!0});var g=m(0),a=L(g),u=m(5),r=L(u),f=m(4),l=L(f),n=m(16),i=L(n),o=m(25),s=L(o),c=m(24),p=L(c),$=m(35),v=L($),C=m(6),y=L(C),_=m(22),b=L(_),E=m(7),x=L(E),O=m(55),M=L(O),k=m(42),T=L(k),S=m(23),w=L(S);function L(q){return q&&q.__esModule?q:{default:q}}r.default.register({"blots/block":l.default,"blots/block/embed":f.BlockEmbed,"blots/break":i.default,"blots/container":s.default,"blots/cursor":p.default,"blots/embed":v.default,"blots/inline":y.default,"blots/scroll":b.default,"blots/text":x.default,"modules/clipboard":M.default,"modules/history":T.default,"modules/keyboard":w.default}),a.default.register(l.default,i.default,p.default,y.default,b.default,x.default),h.default=r.default},function(e,h,m){Object.defineProperty(h,"__esModule",{value:!0});var g=m(1),a=function(){function u(r){this.domNode=r,this.domNode[g.DATA_KEY]={blot:this}}return Object.defineProperty(u.prototype,"statics",{get:function(){return this.constructor},enumerable:!0,configurable:!0}),u.create=function(r){if(this.tagName==null)throw new g.ParchmentError("Blot definition missing tagName");var f;return Array.isArray(this.tagName)?(typeof r=="string"&&(r=r.toUpperCase(),parseInt(r).toString()===r&&(r=parseInt(r))),typeof r=="number"?f=document.createElement(this.tagName[r-1]):this.tagName.indexOf(r)>-1?f=document.createElement(r):f=document.createElement(this.tagName[0])):f=document.createElement(this.tagName),this.className&&f.classList.add(this.className),f},u.prototype.attach=function(){this.parent!=null&&(this.scroll=this.parent.scroll)},u.prototype.clone=function(){var r=this.domNode.cloneNode(!1);return g.create(r)},u.prototype.detach=function(){this.parent!=null&&this.parent.removeChild(this),delete this.domNode[g.DATA_KEY]},u.prototype.deleteAt=function(r,f){var l=this.isolate(r,f);l.remove()},u.prototype.formatAt=function(r,f,l,n){var i=this.isolate(r,f);if(g.query(l,g.Scope.BLOT)!=null&&n)i.wrap(l,n);else if(g.query(l,g.Scope.ATTRIBUTE)!=null){var o=g.create(this.statics.scope);i.wrap(o),o.format(l,n)}},u.prototype.insertAt=function(r,f,l){var n=l==null?g.create("text",f):g.create(f,l),i=this.split(r);this.parent.insertBefore(n,i)},u.prototype.insertInto=function(r,f){f===void 0&&(f=null),this.parent!=null&&this.parent.children.remove(this);var l=null;r.children.insertBefore(this,f),f!=null&&(l=f.domNode),(this.domNode.parentNode!=r.domNode||this.domNode.nextSibling!=l)&&r.domNode.insertBefore(this.domNode,l),this.parent=r,this.attach()},u.prototype.isolate=function(r,f){var l=this.split(r);return l.split(f),l},u.prototype.length=function(){return 1},u.prototype.offset=function(r){return r===void 0&&(r=this.parent),this.parent==null||this==r?0:this.parent.children.offset(this)+this.parent.offset(r)},u.prototype.optimize=function(r){this.domNode[g.DATA_KEY]!=null&&delete this.domNode[g.DATA_KEY].mutations},u.prototype.remove=function(){this.domNode.parentNode!=null&&this.domNode.parentNode.removeChild(this.domNode),this.detach()},u.prototype.replace=function(r){r.parent!=null&&(r.parent.insertBefore(this,r.next),r.remove())},u.prototype.replaceWith=function(r,f){var l=typeof r=="string"?g.create(r,f):r;return l.replace(this),l},u.prototype.split=function(r,f){return r===0?this:this.next},u.prototype.update=function(r,f){},u.prototype.wrap=function(r,f){var l=typeof r=="string"?g.create(r,f):r;return this.parent!=null&&this.parent.insertBefore(l,this.next),l.appendChild(this),l},u.blotName="abstract",u}();h.default=a},function(e,h,m){Object.defineProperty(h,"__esModule",{value:!0});var g=m(12),a=m(32),u=m(33),r=m(1),f=function(){function l(n){this.attributes={},this.domNode=n,this.build()}return l.prototype.attribute=function(n,i){i?n.add(this.domNode,i)&&(n.value(this.domNode)!=null?this.attributes[n.attrName]=n:delete this.attributes[n.attrName]):(n.remove(this.domNode),delete this.attributes[n.attrName])},l.prototype.build=function(){var n=this;this.attributes={};var i=g.default.keys(this.domNode),o=a.default.keys(this.domNode),s=u.default.keys(this.domNode);i.concat(o).concat(s).forEach(function(c){var p=r.query(c,r.Scope.ATTRIBUTE);p instanceof g.default&&(n.attributes[p.attrName]=p)})},l.prototype.copy=function(n){var i=this;Object.keys(this.attributes).forEach(function(o){var s=i.attributes[o].value(i.domNode);n.format(o,s)})},l.prototype.move=function(n){var i=this;this.copy(n),Object.keys(this.attributes).forEach(function(o){i.attributes[o].remove(i.domNode)}),this.attributes={}},l.prototype.values=function(){var n=this;return Object.keys(this.attributes).reduce(function(i,o){return i[o]=n.attributes[o].value(n.domNode),i},{})},l}();h.default=f},function(e,h,m){var g=this&&this.__extends||function(){var f=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(l,n){l.__proto__=n}||function(l,n){for(var i in n)n.hasOwnProperty(i)&&(l[i]=n[i])};return function(l,n){f(l,n);function i(){this.constructor=l}l.prototype=n===null?Object.create(n):(i.prototype=n.prototype,new i)}}();Object.defineProperty(h,"__esModule",{value:!0});var a=m(12);function u(f,l){var n=f.getAttribute("class")||"";return n.split(/\s+/).filter(function(i){return i.indexOf(l+"-")===0})}var r=function(f){g(l,f);function l(){return f!==null&&f.apply(this,arguments)||this}return l.keys=function(n){return(n.getAttribute("class")||"").split(/\s+/).map(function(i){return i.split("-").slice(0,-1).join("-")})},l.prototype.add=function(n,i){return this.canAdd(n,i)?(this.remove(n),n.classList.add(this.keyName+"-"+i),!0):!1},l.prototype.remove=function(n){var i=u(n,this.keyName);i.forEach(function(o){n.classList.remove(o)}),n.classList.length===0&&n.removeAttribute("class")},l.prototype.value=function(n){var i=u(n,this.keyName)[0]||"",o=i.slice(this.keyName.length+1);return this.canAdd(n,o)?o:""},l}(a.default);h.default=r},function(e,h,m){var g=this&&this.__extends||function(){var f=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(l,n){l.__proto__=n}||function(l,n){for(var i in n)n.hasOwnProperty(i)&&(l[i]=n[i])};return function(l,n){f(l,n);function i(){this.constructor=l}l.prototype=n===null?Object.create(n):(i.prototype=n.prototype,new i)}}();Object.defineProperty(h,"__esModule",{value:!0});var a=m(12);function u(f){var l=f.split("-"),n=l.slice(1).map(function(i){return i[0].toUpperCase()+i.slice(1)}).join("");return l[0]+n}var r=function(f){g(l,f);function l(){return f!==null&&f.apply(this,arguments)||this}return l.keys=function(n){return(n.getAttribute("style")||"").split(";").map(function(i){var o=i.split(":");return o[0].trim()})},l.prototype.add=function(n,i){return this.canAdd(n,i)?(n.style[u(this.keyName)]=i,!0):!1},l.prototype.remove=function(n){n.style[u(this.keyName)]="",n.getAttribute("style")||n.removeAttribute("style")},l.prototype.value=function(n){var i=n.style[u(this.keyName)];return this.canAdd(n,i)?i:""},l}(a.default);h.default=r},function(e,h,m){Object.defineProperty(h,"__esModule",{value:!0});var g=function(){function r(f,l){for(var n=0;nO&&this.stack.undo.length>0){var M=this.stack.undo.pop();x=x.compose(M.undo),b=M.redo.compose(b)}else this.lastRecorded=O;this.stack.undo.push({redo:b,undo:x}),this.stack.undo.length>this.options.maxStack&&this.stack.undo.shift()}}},{key:"redo",value:function(){this.change("redo","undo")}},{key:"transform",value:function(b){this.stack.undo.forEach(function(E){E.undo=b.transform(E.undo,!0),E.redo=b.transform(E.redo,!0)}),this.stack.redo.forEach(function(E){E.undo=b.transform(E.undo,!0),E.redo=b.transform(E.redo,!0)})}},{key:"undo",value:function(){this.change("undo","redo")}}]),y}(n.default);p.DEFAULTS={delay:1e3,maxStack:100,userOnly:!1};function $(C){var y=C.ops[C.ops.length-1];return y==null?!1:y.insert!=null?typeof y.insert=="string"&&y.insert.endsWith(` +`):y.attributes!=null?Object.keys(y.attributes).some(function(_){return u.default.query(_,u.default.Scope.BLOCK)!=null}):!1}function v(C){var y=C.reduce(function(b,E){return b+=E.delete||0,b},0),_=C.length()-y;return $(C)&&(_-=1),_}h.default=p,h.getLastChangeIndex=v},function(e,h,m){Object.defineProperty(h,"__esModule",{value:!0}),h.default=h.BaseTooltip=void 0;var g=function(){function B(N,P){for(var j=0;j0&&arguments[0]!==void 0?arguments[0]:"link",D=arguments.length>1&&arguments[1]!==void 0?arguments[1]:null;this.root.classList.remove("ql-hidden"),this.root.classList.add("ql-editing"),D!=null?this.textbox.value=D:j!==this.root.getAttribute("data-mode")&&(this.textbox.value=""),this.position(this.quill.getBounds(this.quill.selection.savedRange)),this.textbox.select(),this.textbox.setAttribute("placeholder",this.textbox.getAttribute("data-"+j)||""),this.root.setAttribute("data-mode",j)}},{key:"restoreFocus",value:function(){var j=this.quill.scrollingContainer.scrollTop;this.quill.focus(),this.quill.scrollingContainer.scrollTop=j}},{key:"save",value:function(){var j=this.textbox.value;switch(this.root.getAttribute("data-mode")){case"link":{var D=this.quill.root.scrollTop;this.linkRange?(this.quill.formatText(this.linkRange,"link",j,i.default.sources.USER),delete this.linkRange):(this.restoreFocus(),this.quill.format("link",j,i.default.sources.USER)),this.quill.root.scrollTop=D;break}case"video":j=V(j);case"formula":{if(!j)break;var W=this.quill.getSelection(!0);if(W!=null){var H=W.index+W.length;this.quill.insertEmbed(H,this.root.getAttribute("data-mode"),j,i.default.sources.USER),this.root.getAttribute("data-mode")==="formula"&&this.quill.insertText(H+1," ",i.default.sources.USER),this.quill.setSelection(H+2,i.default.sources.USER)}break}}this.textbox.value="",this.hide()}}]),N}(x.default);function V(B){var N=B.match(/^(?:(https?):\/\/)?(?:(?:www|m)\.)?youtube\.com\/watch.*v=([a-zA-Z0-9_-]+)/)||B.match(/^(?:(https?):\/\/)?(?:(?:www|m)\.)?youtu\.be\/([a-zA-Z0-9_-]+)/);return N?(N[1]||"https")+"://www.youtube.com/embed/"+N[2]+"?showinfo=0":(N=B.match(/^(?:(https?):\/\/)?(?:www\.)?vimeo\.com\/(\d+)/))?(N[1]||"https")+"://player.vimeo.com/video/"+N[2]+"/":B}function R(B,N){var P=arguments.length>2&&arguments[2]!==void 0?arguments[2]:!1;N.forEach(function(j){var D=document.createElement("option");j===P?D.setAttribute("selected","selected"):D.setAttribute("value",j),B.appendChild(D)})}h.BaseTooltip=F,h.default=I},function(e,h,m){Object.defineProperty(h,"__esModule",{value:!0});var g=function(){function a(){this.head=this.tail=null,this.length=0}return a.prototype.append=function(){for(var u=[],r=0;r1&&this.append.apply(this,u.slice(1))},a.prototype.contains=function(u){for(var r,f=this.iterator();r=f();)if(r===u)return!0;return!1},a.prototype.insertBefore=function(u,r){!u||(u.next=r,r!=null?(u.prev=r.prev,r.prev!=null&&(r.prev.next=u),r.prev=u,r===this.head&&(this.head=u)):this.tail!=null?(this.tail.next=u,u.prev=this.tail,this.tail=u):(u.prev=null,this.head=this.tail=u),this.length+=1)},a.prototype.offset=function(u){for(var r=0,f=this.head;f!=null;){if(f===u)return r;r+=f.length(),f=f.next}return-1},a.prototype.remove=function(u){!this.contains(u)||(u.prev!=null&&(u.prev.next=u.next),u.next!=null&&(u.next.prev=u.prev),u===this.head&&(this.head=u.next),u===this.tail&&(this.tail=u.prev),this.length-=1)},a.prototype.iterator=function(u){return u===void 0&&(u=this.head),function(){var r=u;return u!=null&&(u=u.next),r}},a.prototype.find=function(u,r){r===void 0&&(r=!1);for(var f,l=this.iterator();f=l();){var n=f.length();if(us?f(o,u-s,Math.min(r,s+p-u)):f(o,0,Math.min(p,u+r-s)),s+=p}},a.prototype.map=function(u){return this.reduce(function(r,f){return r.push(u(f)),r},[])},a.prototype.reduce=function(u,r){for(var f,l=this.iterator();f=l();)r=u(r,f);return r},a}();h.default=g},function(e,h,m){var g=this&&this.__extends||function(){var n=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(i,o){i.__proto__=o}||function(i,o){for(var s in o)o.hasOwnProperty(s)&&(i[s]=o[s])};return function(i,o){n(i,o);function s(){this.constructor=i}i.prototype=o===null?Object.create(o):(s.prototype=o.prototype,new s)}}();Object.defineProperty(h,"__esModule",{value:!0});var a=m(17),u=m(1),r={attributes:!0,characterData:!0,characterDataOldValue:!0,childList:!0,subtree:!0},f=100,l=function(n){g(i,n);function i(o){var s=n.call(this,o)||this;return s.scroll=s,s.observer=new MutationObserver(function(c){s.update(c)}),s.observer.observe(s.domNode,r),s.attach(),s}return i.prototype.detach=function(){n.prototype.detach.call(this),this.observer.disconnect()},i.prototype.deleteAt=function(o,s){this.update(),o===0&&s===this.length()?this.children.forEach(function(c){c.remove()}):n.prototype.deleteAt.call(this,o,s)},i.prototype.formatAt=function(o,s,c,p){this.update(),n.prototype.formatAt.call(this,o,s,c,p)},i.prototype.insertAt=function(o,s,c){this.update(),n.prototype.insertAt.call(this,o,s,c)},i.prototype.optimize=function(o,s){var c=this;o===void 0&&(o=[]),s===void 0&&(s={}),n.prototype.optimize.call(this,s);for(var p=[].slice.call(this.observer.takeRecords());p.length>0;)o.push(p.pop());for(var $=function(_,b){b===void 0&&(b=!0),!(_==null||_===c)&&_.domNode.parentNode!=null&&(_.domNode[u.DATA_KEY].mutations==null&&(_.domNode[u.DATA_KEY].mutations=[]),b&&$(_.parent))},v=function(_){_.domNode[u.DATA_KEY]==null||_.domNode[u.DATA_KEY].mutations==null||(_ instanceof a.default&&_.children.forEach(v),_.optimize(s))},C=o,y=0;C.length>0;y+=1){if(y>=f)throw new Error("[Parchment] Maximum optimize iterations reached");for(C.forEach(function(_){var b=u.find(_.target,!0);b!=null&&(b.domNode===_.target&&(_.type==="childList"?($(u.find(_.previousSibling,!1)),[].forEach.call(_.addedNodes,function(E){var x=u.find(E,!1);$(x,!1),x instanceof a.default&&x.children.forEach(function(O){$(O,!1)})})):_.type==="attributes"&&$(b.prev)),$(b))}),this.children.forEach(v),C=[].slice.call(this.observer.takeRecords()),p=C.slice();p.length>0;)o.push(p.pop())}},i.prototype.update=function(o,s){var c=this;s===void 0&&(s={}),o=o||this.observer.takeRecords(),o.map(function(p){var $=u.find(p.target,!0);return $==null?null:$.domNode[u.DATA_KEY].mutations==null?($.domNode[u.DATA_KEY].mutations=[p],$):($.domNode[u.DATA_KEY].mutations.push(p),null)}).forEach(function(p){p==null||p===c||p.domNode[u.DATA_KEY]==null||p.update(p.domNode[u.DATA_KEY].mutations||[],s)}),this.domNode[u.DATA_KEY].mutations!=null&&n.prototype.update.call(this,this.domNode[u.DATA_KEY].mutations,s),this.optimize(o,s)},i.blotName="scroll",i.defaultChild="block",i.scope=u.Scope.BLOCK_BLOT,i.tagName="DIV",i}(a.default);h.default=l},function(e,h,m){var g=this&&this.__extends||function(){var l=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(n,i){n.__proto__=i}||function(n,i){for(var o in i)i.hasOwnProperty(o)&&(n[o]=i[o])};return function(n,i){l(n,i);function o(){this.constructor=n}n.prototype=i===null?Object.create(i):(o.prototype=i.prototype,new o)}}();Object.defineProperty(h,"__esModule",{value:!0});var a=m(18),u=m(1);function r(l,n){if(Object.keys(l).length!==Object.keys(n).length)return!1;for(var i in l)if(l[i]!==n[i])return!1;return!0}var f=function(l){g(n,l);function n(){return l!==null&&l.apply(this,arguments)||this}return n.formats=function(i){if(i.tagName!==n.tagName)return l.formats.call(this,i)},n.prototype.format=function(i,o){var s=this;i===this.statics.blotName&&!o?(this.children.forEach(function(c){c instanceof a.default||(c=c.wrap(n.blotName,!0)),s.attributes.copy(c)}),this.unwrap()):l.prototype.format.call(this,i,o)},n.prototype.formatAt=function(i,o,s,c){if(this.formats()[s]!=null||u.query(s,u.Scope.ATTRIBUTE)){var p=this.isolate(i,o);p.format(s,c)}else l.prototype.formatAt.call(this,i,o,s,c)},n.prototype.optimize=function(i){l.prototype.optimize.call(this,i);var o=this.formats();if(Object.keys(o).length===0)return this.unwrap();var s=this.next;s instanceof n&&s.prev===this&&r(o,s.formats())&&(s.moveChildren(this),s.remove())},n.blotName="inline",n.scope=u.Scope.INLINE_BLOT,n.tagName="SPAN",n}(a.default);h.default=f},function(e,h,m){var g=this&&this.__extends||function(){var f=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(l,n){l.__proto__=n}||function(l,n){for(var i in n)n.hasOwnProperty(i)&&(l[i]=n[i])};return function(l,n){f(l,n);function i(){this.constructor=l}l.prototype=n===null?Object.create(n):(i.prototype=n.prototype,new i)}}();Object.defineProperty(h,"__esModule",{value:!0});var a=m(18),u=m(1),r=function(f){g(l,f);function l(){return f!==null&&f.apply(this,arguments)||this}return l.formats=function(n){var i=u.query(l.blotName).tagName;if(n.tagName!==i)return f.formats.call(this,n)},l.prototype.format=function(n,i){u.query(n,u.Scope.BLOCK)!=null&&(n===this.statics.blotName&&!i?this.replaceWith(l.blotName):f.prototype.format.call(this,n,i))},l.prototype.formatAt=function(n,i,o,s){u.query(o,u.Scope.BLOCK)!=null?this.format(o,s):f.prototype.formatAt.call(this,n,i,o,s)},l.prototype.insertAt=function(n,i,o){if(o==null||u.query(i,u.Scope.INLINE)!=null)f.prototype.insertAt.call(this,n,i,o);else{var s=this.split(n),c=u.create(i,o);s.parent.insertBefore(c,s)}},l.prototype.update=function(n,i){navigator.userAgent.match(/Trident/)?this.build():f.prototype.update.call(this,n,i)},l.blotName="block",l.scope=u.Scope.BLOCK_BLOT,l.tagName="P",l}(a.default);h.default=r},function(e,h,m){var g=this&&this.__extends||function(){var r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(f,l){f.__proto__=l}||function(f,l){for(var n in l)l.hasOwnProperty(n)&&(f[n]=l[n])};return function(f,l){r(f,l);function n(){this.constructor=f}f.prototype=l===null?Object.create(l):(n.prototype=l.prototype,new n)}}();Object.defineProperty(h,"__esModule",{value:!0});var a=m(19),u=function(r){g(f,r);function f(){return r!==null&&r.apply(this,arguments)||this}return f.formats=function(l){},f.prototype.format=function(l,n){r.prototype.formatAt.call(this,0,this.length(),l,n)},f.prototype.formatAt=function(l,n,i,o){l===0&&n===this.length()?this.format(i,o):r.prototype.formatAt.call(this,l,n,i,o)},f.prototype.formats=function(){return this.statics.formats(this.domNode)},f}(a.default);h.default=u},function(e,h,m){var g=this&&this.__extends||function(){var f=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(l,n){l.__proto__=n}||function(l,n){for(var i in n)n.hasOwnProperty(i)&&(l[i]=n[i])};return function(l,n){f(l,n);function i(){this.constructor=l}l.prototype=n===null?Object.create(n):(i.prototype=n.prototype,new i)}}();Object.defineProperty(h,"__esModule",{value:!0});var a=m(19),u=m(1),r=function(f){g(l,f);function l(n){var i=f.call(this,n)||this;return i.text=i.statics.value(i.domNode),i}return l.create=function(n){return document.createTextNode(n)},l.value=function(n){var i=n.data;return i.normalize&&(i=i.normalize()),i},l.prototype.deleteAt=function(n,i){this.domNode.data=this.text=this.text.slice(0,n)+this.text.slice(n+i)},l.prototype.index=function(n,i){return this.domNode===n?i:-1},l.prototype.insertAt=function(n,i,o){o==null?(this.text=this.text.slice(0,n)+i+this.text.slice(n),this.domNode.data=this.text):f.prototype.insertAt.call(this,n,i,o)},l.prototype.length=function(){return this.text.length},l.prototype.optimize=function(n){f.prototype.optimize.call(this,n),this.text=this.statics.value(this.domNode),this.text.length===0?this.remove():this.next instanceof l&&this.next.prev===this&&(this.insertAt(this.length(),this.next.value()),this.next.remove())},l.prototype.position=function(n,i){return[this.domNode,n]},l.prototype.split=function(n,i){if(i===void 0&&(i=!1),!i){if(n===0)return this;if(n===this.length())return this.next}var o=u.create(this.domNode.splitText(n));return this.parent.insertBefore(o,this.next),this.text=this.statics.value(this.domNode),o},l.prototype.update=function(n,i){var o=this;n.some(function(s){return s.type==="characterData"&&s.target===o.domNode})&&(this.text=this.statics.value(this.domNode))},l.prototype.value=function(){return this.text},l.blotName="text",l.scope=u.Scope.INLINE_BLOT,l}(a.default);h.default=r},function(e,h,m){var g=document.createElement("div");if(g.classList.toggle("test-class",!1),g.classList.contains("test-class")){var a=DOMTokenList.prototype.toggle;DOMTokenList.prototype.toggle=function(u,r){return arguments.length>1&&!this.contains(u)==!r?r:a.call(this,u)}}String.prototype.startsWith||(String.prototype.startsWith=function(u,r){return r=r||0,this.substr(r,u.length)===u}),String.prototype.endsWith||(String.prototype.endsWith=function(u,r){var f=this.toString();(typeof r!="number"||!isFinite(r)||Math.floor(r)!==r||r>f.length)&&(r=f.length),r-=u.length;var l=f.indexOf(u,r);return l!==-1&&l===r}),Array.prototype.find||Object.defineProperty(Array.prototype,"find",{value:function(r){if(this===null)throw new TypeError("Array.prototype.find called on null or undefined");if(typeof r!="function")throw new TypeError("predicate must be a function");for(var f=Object(this),l=f.length>>>0,n=arguments[1],i,o=0;o_.length?y:_,x=y.length>_.length?_:y,O=E.indexOf(x);if(O!=-1)return b=[[g,E.substring(0,O)],[a,x],[g,E.substring(O+x.length)]],y.length>_.length&&(b[0][0]=b[2][0]=m),b;if(x.length==1)return[[m,y],[g,_]];var M=o(y,_);if(M){var k=M[0],T=M[1],S=M[2],w=M[3],L=M[4],q=u(k,S),A=u(T,w);return q.concat([[a,L]],A)}return f(y,_)}function f(y,_){for(var b=y.length,E=_.length,x=Math.ceil((b+E)/2),O=x,M=2*x,k=new Array(M),T=new Array(M),S=0;Sb)A+=2;else if(P>E)q+=2;else if(L){var j=O+w-R;if(j>=0&&j=D)return l(y,_,N,P)}}}for(var W=-V+I;W<=V-F;W+=2){var j=O+W,D;W==-V||W!=V&&T[j-1]b)F+=2;else if(H>E)I+=2;else if(!L){var B=O+w-W;if(B>=0&&B=D)return l(y,_,N,P)}}}}return[[m,y],[g,_]]}function l(y,_,b,E){var x=y.substring(0,b),O=_.substring(0,E),M=y.substring(b),k=_.substring(E),T=u(x,O),S=u(M,k);return T.concat(S)}function n(y,_){if(!y||!_||y.charAt(0)!=_.charAt(0))return 0;for(var b=0,E=Math.min(y.length,_.length),x=E,O=0;b_.length?y:_,E=y.length>_.length?_:y;if(b.length<4||E.length*2=A.length?[N,P,j,D,B]:null}var O=x(b,E,Math.ceil(b.length/4)),M=x(b,E,Math.ceil(b.length/2)),k;if(!O&&!M)return null;M?O?k=O[4].length>M[4].length?O:M:k=M:k=O;var T,S,w,L;y.length>_.length?(T=k[0],S=k[1],w=k[2],L=k[3]):(w=k[0],L=k[1],T=k[2],S=k[3]);var q=k[4];return[T,S,w,L,q]}function s(y){y.push([a,""]);for(var _=0,b=0,E=0,x="",O="",M;_1?(b!==0&&E!==0&&(M=n(O,x),M!==0&&(_-b-E>0&&y[_-b-E-1][0]==a?y[_-b-E-1][1]+=O.substring(0,M):(y.splice(0,0,[a,O.substring(0,M)]),_++),O=O.substring(M),x=x.substring(M)),M=i(O,x),M!==0&&(y[_][1]=O.substring(O.length-M)+y[_][1],O=O.substring(0,O.length-M),x=x.substring(0,x.length-M))),b===0?y.splice(_-E,b+E,[g,O]):E===0?y.splice(_-b,b+E,[m,x]):y.splice(_-b-E,b+E,[m,x],[g,O]),_=_-b-E+(b?1:0)+(E?1:0)+1):_!==0&&y[_-1][0]==a?(y[_-1][1]+=y[_][1],y.splice(_,1)):_++,E=0,b=0,x="",O="";break}y[y.length-1][1]===""&&y.pop();var k=!1;for(_=1;_0&&E.splice(x+2,0,[M[0],k]),C(E,x,3)}else return y}function v(y){for(var _=!1,b=function(M){return M.charCodeAt(0)>=56320&&M.charCodeAt(0)<=57343},E=function(M){return M.charCodeAt(M.length-1)>=55296&&M.charCodeAt(M.length-1)<=56319},x=2;x0&&O.push(y[x]);return O}function C(y,_,b){for(var E=_+b-1;E>=0&&E>=_-1;E--)if(E+1\r?\n +\<"),this.convert();var te=this.quill.getFormat(this.quill.selection.savedRange.index);if(te[E.default.blotName]){var me=this.container.innerText;return this.container.innerHTML="",new n.default().insert(me,S({},E.default.blotName,te[E.default.blotName]))}var $e=this.prepareMatching(),be=a($e,2),X=be[0],ae=be[1],oe=W(this.container,X,ae);return j(oe,` +`)&&oe.ops[oe.ops.length-1].attributes==null&&(oe=oe.compose(new n.default().retain(oe.length()-1).delete(1))),A.log("convert",this.container.innerHTML,oe),this.container.innerHTML="",oe}},{key:"dangerouslyPasteHTML",value:function(le,te){var me=arguments.length>2&&arguments[2]!==void 0?arguments[2]:c.default.sources.API;if(typeof le=="string")this.quill.setContents(this.convert(le),te),this.quill.setSelection(0,c.default.sources.SILENT);else{var $e=this.convert(te);this.quill.updateContents(new n.default().retain(le).concat($e),me),this.quill.setSelection(le+$e.length(),c.default.sources.SILENT)}}},{key:"onPaste",value:function(le){var te=this;if(!(le.defaultPrevented||!this.quill.isEnabled())){var me=this.quill.getSelection(),$e=new n.default().retain(me.index),be=this.quill.scrollingContainer.scrollTop;this.container.focus(),this.quill.selection.update(c.default.sources.SILENT),setTimeout(function(){$e=$e.concat(te.convert()).delete(me.length),te.quill.updateContents($e,c.default.sources.USER),te.quill.setSelection($e.length()-me.length,c.default.sources.SILENT),te.quill.scrollingContainer.scrollTop=be,te.quill.focus()},1)}}},{key:"prepareMatching",value:function(){var le=this,te=[],me=[];return this.matchers.forEach(function($e){var be=a($e,2),X=be[0],ae=be[1];switch(X){case Node.TEXT_NODE:me.push(ae);break;case Node.ELEMENT_NODE:te.push(ae);break;default:[].forEach.call(le.container.querySelectorAll(X),function(oe){oe[I]=oe[I]||[],oe[I].push(ae)});break}}),[te,me]}}]),Q}(C.default);B.DEFAULTS={matchers:[],matchVisual:!0};function N(J,Q,ne){return(typeof Q=="undefined"?"undefined":g(Q))==="object"?Object.keys(Q).reduce(function(le,te){return N(le,te,Q[te])},J):J.reduce(function(le,te){return te.attributes&&te.attributes[Q]?le.push(te):le.insert(te.insert,(0,f.default)({},S({},Q,ne),te.attributes))},new n.default)}function P(J){if(J.nodeType!==Node.ELEMENT_NODE)return{};var Q="__ql-computed-style";return J[Q]||(J[Q]=window.getComputedStyle(J))}function j(J,Q){for(var ne="",le=J.ops.length-1;le>=0&&ne.length-1}function W(J,Q,ne){return J.nodeType===J.TEXT_NODE?ne.reduce(function(le,te){return te(J,le)},new n.default):J.nodeType===J.ELEMENT_NODE?[].reduce.call(J.childNodes||[],function(le,te){var me=W(te,Q,ne);return te.nodeType===J.ELEMENT_NODE&&(me=Q.reduce(function($e,be){return be(te,$e)},me),me=(te[I]||[]).reduce(function($e,be){return be(te,$e)},me)),le.concat(me)},new n.default):new n.default}function H(J,Q,ne){return N(ne,J,!0)}function z(J,Q){var ne=o.default.Attributor.Attribute.keys(J),le=o.default.Attributor.Class.keys(J),te=o.default.Attributor.Style.keys(J),me={};return ne.concat(le).concat(te).forEach(function($e){var be=o.default.query($e,o.default.Scope.ATTRIBUTE);be!=null&&(me[be.attrName]=be.value(J),me[be.attrName])||(be=V[$e],be!=null&&(be.attrName===$e||be.keyName===$e)&&(me[be.attrName]=be.value(J)||void 0),be=R[$e],be!=null&&(be.attrName===$e||be.keyName===$e)&&(be=R[$e],me[be.attrName]=be.value(J)||void 0))}),Object.keys(me).length>0&&(Q=N(Q,me)),Q}function K(J,Q){var ne=o.default.query(J);if(ne==null)return Q;if(ne.prototype instanceof o.default.Embed){var le={},te=ne.value(J);te!=null&&(le[ne.blotName]=te,Q=new n.default().insert(le,ne.formats(J)))}else typeof ne.formats=="function"&&(Q=N(Q,ne.blotName,ne.formats(J)));return Q}function Z(J,Q){return j(Q,` +`)||Q.insert(` +`),Q}function ie(){return new n.default}function se(J,Q){var ne=o.default.query(J);if(ne==null||ne.blotName!=="list-item"||!j(Q,` +`))return Q;for(var le=-1,te=J.parentNode;!te.classList.contains("ql-clipboard");)(o.default.query(te)||{}).blotName==="list"&&(le+=1),te=te.parentNode;return le<=0?Q:Q.compose(new n.default().retain(Q.length()-1).retain(1,{indent:le}))}function ue(J,Q){return j(Q,` +`)||(D(J)||Q.length()>0&&J.nextSibling&&D(J.nextSibling))&&Q.insert(` +`),Q}function fe(J,Q){if(D(J)&&J.nextElementSibling!=null&&!j(Q,` + +`)){var ne=J.offsetHeight+parseFloat(P(J).marginTop)+parseFloat(P(J).marginBottom);J.nextElementSibling.offsetTop>J.offsetTop+ne*1.5&&Q.insert(` +`)}return Q}function ye(J,Q){var ne={},le=J.style||{};return le.fontStyle&&P(J).fontStyle==="italic"&&(ne.italic=!0),le.fontWeight&&(P(J).fontWeight.startsWith("bold")||parseInt(P(J).fontWeight)>=700)&&(ne.bold=!0),Object.keys(ne).length>0&&(Q=N(Q,ne)),parseFloat(le.textIndent||0)>0&&(Q=new n.default().insert(" ").concat(Q)),Q}function _e(J,Q){var ne=J.data;if(J.parentNode.tagName==="O:P")return Q.insert(ne.trim());if(ne.trim().length===0&&J.parentNode.classList.contains("ql-clipboard"))return Q;if(!P(J.parentNode).whiteSpace.startsWith("pre")){var le=function(me,$e){return $e=$e.replace(/[^\u00a0]/g,""),$e.length<1&&me?" ":$e};ne=ne.replace(/\r\n/g," ").replace(/\n/g," "),ne=ne.replace(/\s\s+/g,le.bind(le,!0)),(J.previousSibling==null&&D(J.parentNode)||J.previousSibling!=null&&D(J.previousSibling))&&(ne=ne.replace(/^\s+/,le.bind(le,!1))),(J.nextSibling==null&&D(J.parentNode)||J.nextSibling!=null&&D(J.nextSibling))&&(ne=ne.replace(/\s+$/,le.bind(le,!1)))}return Q.insert(ne)}h.default=B,h.matchAttributor=z,h.matchBlot=K,h.matchNewline=ue,h.matchSpacing=fe,h.matchText=_e},function(e,h,m){Object.defineProperty(h,"__esModule",{value:!0});var g=function(){function s(c,p){for(var $=0;$ '},function(e,h,m){Object.defineProperty(h,"__esModule",{value:!0});var g=function(){function s(c,p){for(var $=0;$o.right&&(c=o.right-s.right,this.root.style.left=n+c+"px"),s.lefto.bottom){var p=s.bottom-s.top,$=l.bottom-l.top+p;this.root.style.top=i-$+"px",this.root.classList.add("ql-flip")}return c}},{key:"show",value:function(){this.root.classList.remove("ql-editing"),this.root.classList.remove("ql-hidden")}}]),r}();h.default=u},function(e,h,m){Object.defineProperty(h,"__esModule",{value:!0});var g=function(){function M(k,T){var S=[],w=!0,L=!1,q=void 0;try{for(var A=k[Symbol.iterator](),I;!(w=(I=A.next()).done)&&(S.push(I.value),!(T&&S.length===T));w=!0);}catch(F){L=!0,q=F}finally{try{!w&&A.return&&A.return()}finally{if(L)throw q}}return S}return function(k,T){if(Array.isArray(k))return k;if(Symbol.iterator in Object(k))return M(k,T);throw new TypeError("Invalid attempt to destructure non-iterable instance")}}(),a=function M(k,T,S){k===null&&(k=Function.prototype);var w=Object.getOwnPropertyDescriptor(k,T);if(w===void 0){var L=Object.getPrototypeOf(k);return L===null?void 0:M(L,T,S)}else{if("value"in w)return w.value;var q=w.get;return q===void 0?void 0:q.call(S)}},u=function(){function M(k,T){for(var S=0;S','','',''].join(""),h.default=x},function(e,h,m){Object.defineProperty(h,"__esModule",{value:!0});var g=m(29),a=te(g),u=m(36),r=m(38),f=m(64),l=m(65),n=te(l),i=m(66),o=te(i),s=m(67),c=te(s),p=m(37),$=m(26),v=m(39),C=m(40),y=m(56),_=te(y),b=m(68),E=te(b),x=m(27),O=te(x),M=m(69),k=te(M),T=m(70),S=te(T),w=m(71),L=te(w),q=m(72),A=te(q),I=m(73),F=te(I),V=m(13),R=te(V),B=m(74),N=te(B),P=m(75),j=te(P),D=m(57),W=te(D),H=m(41),z=te(H),K=m(28),Z=te(K),ie=m(59),se=te(ie),ue=m(60),fe=te(ue),ye=m(61),_e=te(ye),J=m(108),Q=te(J),ne=m(62),le=te(ne);function te(me){return me&&me.__esModule?me:{default:me}}a.default.register({"attributors/attribute/direction":r.DirectionAttribute,"attributors/class/align":u.AlignClass,"attributors/class/background":p.BackgroundClass,"attributors/class/color":$.ColorClass,"attributors/class/direction":r.DirectionClass,"attributors/class/font":v.FontClass,"attributors/class/size":C.SizeClass,"attributors/style/align":u.AlignStyle,"attributors/style/background":p.BackgroundStyle,"attributors/style/color":$.ColorStyle,"attributors/style/direction":r.DirectionStyle,"attributors/style/font":v.FontStyle,"attributors/style/size":C.SizeStyle},!0),a.default.register({"formats/align":u.AlignClass,"formats/direction":r.DirectionClass,"formats/indent":f.IndentClass,"formats/background":p.BackgroundStyle,"formats/color":$.ColorStyle,"formats/font":v.FontClass,"formats/size":C.SizeClass,"formats/blockquote":n.default,"formats/code-block":R.default,"formats/header":o.default,"formats/list":c.default,"formats/bold":_.default,"formats/code":V.Code,"formats/italic":E.default,"formats/link":O.default,"formats/script":k.default,"formats/strike":S.default,"formats/underline":L.default,"formats/image":A.default,"formats/video":F.default,"formats/list/item":s.ListItem,"modules/formula":N.default,"modules/syntax":j.default,"modules/toolbar":W.default,"themes/bubble":Q.default,"themes/snow":le.default,"ui/icons":z.default,"ui/picker":Z.default,"ui/icon-picker":fe.default,"ui/color-picker":se.default,"ui/tooltip":_e.default},!0),h.default=a.default},function(e,h,m){Object.defineProperty(h,"__esModule",{value:!0}),h.IndentClass=void 0;var g=function(){function c(p,$){for(var v=0;v<$.length;v++){var C=$[v];C.enumerable=C.enumerable||!1,C.configurable=!0,"value"in C&&(C.writable=!0),Object.defineProperty(p,C.key,C)}}return function(p,$,v){return $&&c(p.prototype,$),v&&c(p,v),p}}(),a=function c(p,$,v){p===null&&(p=Function.prototype);var C=Object.getOwnPropertyDescriptor(p,$);if(C===void 0){var y=Object.getPrototypeOf(p);return y===null?void 0:c(y,$,v)}else{if("value"in C)return C.value;var _=C.get;return _===void 0?void 0:_.call(v)}},u=m(0),r=f(u);function f(c){return c&&c.__esModule?c:{default:c}}function l(c,p){if(!(c instanceof p))throw new TypeError("Cannot call a class as a function")}function n(c,p){if(!c)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return p&&(typeof p=="object"||typeof p=="function")?p:c}function i(c,p){if(typeof p!="function"&&p!==null)throw new TypeError("Super expression must either be null or a function, not "+typeof p);c.prototype=Object.create(p&&p.prototype,{constructor:{value:c,enumerable:!1,writable:!0,configurable:!0}}),p&&(Object.setPrototypeOf?Object.setPrototypeOf(c,p):c.__proto__=p)}var o=function(c){i(p,c);function p(){return l(this,p),n(this,(p.__proto__||Object.getPrototypeOf(p)).apply(this,arguments))}return g(p,[{key:"add",value:function(v,C){if(C==="+1"||C==="-1"){var y=this.value(v)||0;C=C==="+1"?y+1:y-1}return C===0?(this.remove(v),!0):a(p.prototype.__proto__||Object.getPrototypeOf(p.prototype),"add",this).call(this,v,C)}},{key:"canAdd",value:function(v,C){return a(p.prototype.__proto__||Object.getPrototypeOf(p.prototype),"canAdd",this).call(this,v,C)||a(p.prototype.__proto__||Object.getPrototypeOf(p.prototype),"canAdd",this).call(this,v,parseInt(C))}},{key:"value",value:function(v){return parseInt(a(p.prototype.__proto__||Object.getPrototypeOf(p.prototype),"value",this).call(this,v))||void 0}}]),p}(r.default.Attributor.Class),s=new o("indent","ql-indent",{scope:r.default.Scope.BLOCK,whitelist:[1,2,3,4,5,6,7,8]});h.IndentClass=s},function(e,h,m){Object.defineProperty(h,"__esModule",{value:!0});var g=m(4),a=u(g);function u(i){return i&&i.__esModule?i:{default:i}}function r(i,o){if(!(i instanceof o))throw new TypeError("Cannot call a class as a function")}function f(i,o){if(!i)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return o&&(typeof o=="object"||typeof o=="function")?o:i}function l(i,o){if(typeof o!="function"&&o!==null)throw new TypeError("Super expression must either be null or a function, not "+typeof o);i.prototype=Object.create(o&&o.prototype,{constructor:{value:i,enumerable:!1,writable:!0,configurable:!0}}),o&&(Object.setPrototypeOf?Object.setPrototypeOf(i,o):i.__proto__=o)}var n=function(i){l(o,i);function o(){return r(this,o),f(this,(o.__proto__||Object.getPrototypeOf(o)).apply(this,arguments))}return o}(a.default);n.blotName="blockquote",n.tagName="blockquote",h.default=n},function(e,h,m){Object.defineProperty(h,"__esModule",{value:!0});var g=function(){function o(s,c){for(var p=0;p0&&this.children.tail.format(E,x)}},{key:"formats",value:function(){return s({},this.statics.blotName,this.statics.formats(this.domNode))}},{key:"insertBefore",value:function(E,x){if(E instanceof v)a(_.prototype.__proto__||Object.getPrototypeOf(_.prototype),"insertBefore",this).call(this,E,x);else{var O=x==null?this.length():x.offset(this),M=this.split(O);M.parent.insertBefore(E,M)}}},{key:"optimize",value:function(E){a(_.prototype.__proto__||Object.getPrototypeOf(_.prototype),"optimize",this).call(this,E);var x=this.next;x!=null&&x.prev===this&&x.statics.blotName===this.statics.blotName&&x.domNode.tagName===this.domNode.tagName&&x.domNode.getAttribute("data-checked")===this.domNode.getAttribute("data-checked")&&(x.moveChildren(this),x.remove())}},{key:"replace",value:function(E){if(E.statics.blotName!==this.statics.blotName){var x=r.default.create(this.statics.defaultChild);E.moveChildren(x),this.appendChild(x)}a(_.prototype.__proto__||Object.getPrototypeOf(_.prototype),"replace",this).call(this,E)}}]),_}(i.default);C.blotName="list",C.scope=r.default.Scope.BLOCK_BLOT,C.tagName=["OL","UL"],C.defaultChild="list-item",C.allowedChildren=[v],h.ListItem=v,h.default=C},function(e,h,m){Object.defineProperty(h,"__esModule",{value:!0});var g=m(56),a=u(g);function u(i){return i&&i.__esModule?i:{default:i}}function r(i,o){if(!(i instanceof o))throw new TypeError("Cannot call a class as a function")}function f(i,o){if(!i)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return o&&(typeof o=="object"||typeof o=="function")?o:i}function l(i,o){if(typeof o!="function"&&o!==null)throw new TypeError("Super expression must either be null or a function, not "+typeof o);i.prototype=Object.create(o&&o.prototype,{constructor:{value:i,enumerable:!1,writable:!0,configurable:!0}}),o&&(Object.setPrototypeOf?Object.setPrototypeOf(i,o):i.__proto__=o)}var n=function(i){l(o,i);function o(){return r(this,o),f(this,(o.__proto__||Object.getPrototypeOf(o)).apply(this,arguments))}return o}(a.default);n.blotName="italic",n.tagName=["EM","I"],h.default=n},function(e,h,m){Object.defineProperty(h,"__esModule",{value:!0});var g=function(){function s(c,p){for(var $=0;$-1?y?this.domNode.setAttribute(C,y):this.domNode.removeAttribute(C):a($.prototype.__proto__||Object.getPrototypeOf($.prototype),"format",this).call(this,C,y)}}],[{key:"create",value:function(C){var y=a($.__proto__||Object.getPrototypeOf($),"create",this).call(this,C);return typeof C=="string"&&y.setAttribute("src",this.sanitize(C)),y}},{key:"formats",value:function(C){return s.reduce(function(y,_){return C.hasAttribute(_)&&(y[_]=C.getAttribute(_)),y},{})}},{key:"match",value:function(C){return/\.(jpe?g|gif|png)$/.test(C)||/^data:image\/.+;base64/.test(C)}},{key:"sanitize",value:function(C){return(0,f.sanitize)(C,["http","https","data"])?C:"//:0"}},{key:"value",value:function(C){return C.getAttribute("src")}}]),$}(r.default.Embed);c.blotName="image",c.tagName="IMG",h.default=c},function(e,h,m){Object.defineProperty(h,"__esModule",{value:!0});var g=function(){function p($,v){for(var C=0;C-1?y?this.domNode.setAttribute(C,y):this.domNode.removeAttribute(C):a($.prototype.__proto__||Object.getPrototypeOf($.prototype),"format",this).call(this,C,y)}}],[{key:"create",value:function(C){var y=a($.__proto__||Object.getPrototypeOf($),"create",this).call(this,C);return y.setAttribute("frameborder","0"),y.setAttribute("allowfullscreen",!0),y.setAttribute("src",this.sanitize(C)),y}},{key:"formats",value:function(C){return s.reduce(function(y,_){return C.hasAttribute(_)&&(y[_]=C.getAttribute(_)),y},{})}},{key:"sanitize",value:function(C){return f.default.sanitize(C)}},{key:"value",value:function(C){return C.getAttribute("src")}}]),$}(u.BlockEmbed);c.blotName="video",c.className="ql-video",c.tagName="IFRAME",h.default=c},function(e,h,m){Object.defineProperty(h,"__esModule",{value:!0}),h.default=h.FormulaBlot=void 0;var g=function(){function C(y,_){for(var b=0;b<_.length;b++){var E=_[b];E.enumerable=E.enumerable||!1,E.configurable=!0,"value"in E&&(E.writable=!0),Object.defineProperty(y,E.key,E)}}return function(y,_,b){return _&&C(y.prototype,_),b&&C(y,b),y}}(),a=function C(y,_,b){y===null&&(y=Function.prototype);var E=Object.getOwnPropertyDescriptor(y,_);if(E===void 0){var x=Object.getPrototypeOf(y);return x===null?void 0:C(x,_,b)}else{if("value"in E)return E.value;var O=E.get;return O===void 0?void 0:O.call(b)}},u=m(35),r=o(u),f=m(5),l=o(f),n=m(9),i=o(n);function o(C){return C&&C.__esModule?C:{default:C}}function s(C,y){if(!(C instanceof y))throw new TypeError("Cannot call a class as a function")}function c(C,y){if(!C)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return y&&(typeof y=="object"||typeof y=="function")?y:C}function p(C,y){if(typeof y!="function"&&y!==null)throw new TypeError("Super expression must either be null or a function, not "+typeof y);C.prototype=Object.create(y&&y.prototype,{constructor:{value:C,enumerable:!1,writable:!0,configurable:!0}}),y&&(Object.setPrototypeOf?Object.setPrototypeOf(C,y):C.__proto__=y)}var $=function(C){p(y,C);function y(){return s(this,y),c(this,(y.__proto__||Object.getPrototypeOf(y)).apply(this,arguments))}return g(y,null,[{key:"create",value:function(b){var E=a(y.__proto__||Object.getPrototypeOf(y),"create",this).call(this,b);return typeof b=="string"&&(window.katex.render(b,E,{throwOnError:!1,errorColor:"#f00"}),E.setAttribute("data-value",b)),E}},{key:"value",value:function(b){return b.getAttribute("data-value")}}]),y}(r.default);$.blotName="formula",$.className="ql-formula",$.tagName="SPAN";var v=function(C){p(y,C),g(y,null,[{key:"register",value:function(){l.default.register($,!0)}}]);function y(){s(this,y);var _=c(this,(y.__proto__||Object.getPrototypeOf(y)).call(this));if(window.katex==null)throw new Error("Formula module requires KaTeX.");return _}return y}(i.default);h.FormulaBlot=$,h.default=v},function(e,h,m){Object.defineProperty(h,"__esModule",{value:!0}),h.default=h.CodeToken=h.CodeBlock=void 0;var g=function(){function b(E,x){for(var O=0;O0||this.cachedText==null)&&(this.domNode.innerHTML=O(M),this.domNode.normalize(),this.attach()),this.cachedText=M)}}]),E}(s.default);C.className="ql-syntax";var y=new r.default.Attributor.Class("token","hljs",{scope:r.default.Scope.INLINE}),_=function(b){v(E,b),g(E,null,[{key:"register",value:function(){l.default.register(y,!0),l.default.register(C,!0)}}]);function E(x,O){p(this,E);var M=$(this,(E.__proto__||Object.getPrototypeOf(E)).call(this,x,O));if(typeof M.options.highlight!="function")throw new Error("Syntax module requires highlight.js. Please include the library on the page before Quill.");var k=null;return M.quill.on(l.default.events.SCROLL_OPTIMIZE,function(){clearTimeout(k),k=setTimeout(function(){M.highlight(),k=null},M.options.interval)}),M.highlight(),M}return g(E,[{key:"highlight",value:function(){var O=this;if(!this.quill.selection.composing){this.quill.update(l.default.sources.USER);var M=this.quill.getSelection();this.quill.scroll.descendants(C).forEach(function(k){k.highlight(O.options.highlight)}),this.quill.update(l.default.sources.SILENT),M!=null&&this.quill.setSelection(M,l.default.sources.SILENT)}}}]),E}(i.default);_.DEFAULTS={highlight:function(){return window.hljs==null?null:function(b){var E=window.hljs.highlightAuto(b);return E.value}}(),interval:1e3},h.CodeBlock=C,h.CodeToken=y,h.default=_},function(e,h){e.exports=' '},function(e,h){e.exports=' '},function(e,h){e.exports=' '},function(e,h){e.exports=' '},function(e,h){e.exports=' '},function(e,h){e.exports=' '},function(e,h){e.exports=' '},function(e,h){e.exports=' '},function(e,h){e.exports=' '},function(e,h){e.exports=' '},function(e,h){e.exports=' '},function(e,h){e.exports=' '},function(e,h){e.exports=' '},function(e,h){e.exports=' '},function(e,h){e.exports=' '},function(e,h){e.exports=' '},function(e,h){e.exports=' '},function(e,h){e.exports=' '},function(e,h){e.exports=' '},function(e,h){e.exports=' '},function(e,h){e.exports=' '},function(e,h){e.exports=' '},function(e,h){e.exports=' '},function(e,h){e.exports=' '},function(e,h){e.exports=' '},function(e,h){e.exports=' '},function(e,h){e.exports=' '},function(e,h){e.exports=' '},function(e,h){e.exports=' '},function(e,h){e.exports=' '},function(e,h){e.exports=' '},function(e,h){e.exports=' '},function(e,h,m){Object.defineProperty(h,"__esModule",{value:!0}),h.default=h.BubbleTooltip=void 0;var g=function E(x,O,M){x===null&&(x=Function.prototype);var k=Object.getOwnPropertyDescriptor(x,O);if(k===void 0){var T=Object.getPrototypeOf(x);return T===null?void 0:E(T,O,M)}else{if("value"in k)return k.value;var S=k.get;return S===void 0?void 0:S.call(M)}},a=function(){function E(x,O){for(var M=0;M0&&L===l.default.sources.USER){k.show(),k.root.style.left="0px",k.root.style.width="",k.root.style.width=k.root.offsetWidth+"px";var q=k.quill.getLines(S.index,S.length);if(q.length===1)k.position(k.quill.getBounds(S));else{var A=q[q.length-1],I=k.quill.getIndex(A),F=Math.min(A.length()-1,S.index+S.length-I),V=k.quill.getBounds(new o.Range(I,F));k.position(V)}}else document.activeElement!==k.textbox&&k.quill.hasFocus()&&k.hide()}),k}return a(x,[{key:"listen",value:function(){var M=this;g(x.prototype.__proto__||Object.getPrototypeOf(x.prototype),"listen",this).call(this),this.root.querySelector(".ql-close").addEventListener("click",function(){M.root.classList.remove("ql-editing")}),this.quill.on(l.default.events.SCROLL_OPTIMIZE,function(){setTimeout(function(){if(!M.root.classList.contains("ql-hidden")){var k=M.quill.getSelection();k!=null&&M.position(M.quill.getBounds(k))}},1)})}},{key:"cancel",value:function(){this.show()}},{key:"position",value:function(M){var k=g(x.prototype.__proto__||Object.getPrototypeOf(x.prototype),"position",this).call(this,M),T=this.root.querySelector(".ql-tooltip-arrow");if(T.style.marginLeft="",k===0)return k;T.style.marginLeft=-1*k-T.offsetWidth/2+"px"}}]),x}(n.BaseTooltip);b.TEMPLATE=['','
','','',"
"].join(""),h.BubbleTooltip=b,h.default=_},function(e,h,m){e.exports=m(63)}]).default})})(quill);var Quill=getDefaultExportFromCjs(quill.exports),quill_core="",quill_snow="",quill_bubble="";const defaultOptions={theme:"snow",boundary:document.body,modules:{toolbar:[["bold","italic","underline","strike"],["blockquote","code-block"],[{header:1},{header:2}],[{list:"ordered"},{list:"bullet"}],[{script:"sub"},{script:"super"}],[{indent:"-1"},{indent:"+1"}],[{direction:"rtl"}],[{size:["small",!1,"large","huge"]}],[{header:[1,2,3,4,5,6,!1]}],[{color:[]},{background:[]}],[{font:[]}],[{align:[]}],["clean"],["link","image","video"]]},placeholder:"Insert content here ...",readOnly:!1},_sfc_main$2S={name:"quill-editor",props:{content:String,value:String,disabled:{type:Boolean,default:!1},options:{type:Object,required:!1,default:()=>({})}},emits:["ready","change","input","blur","focus","update:value"],setup(t,d){const e={editorOption:{},quill:null};let h="";require$$0$1.watch(()=>t.value,u=>{e.quill&&(u&&u!==h?(h=u,e.quill.pasteHTML(u)):u||e.quill.setText(""))}),require$$0$1.watch(()=>t.content,u=>{e.quill&&(u&&u!==h?(h=u,e.quill.pasteHTML(u)):u||e.quill.setText(""))}),require$$0$1.watch(()=>t.disabled,u=>{e.quill&&e.quill.enable(!u)});const m=require$$0$1.ref(null),g=(u,r)=>{for(const f in r)!u[f]||f!=="modules"?u[f]=r[f]:g(u[f],r[f]);return u},a=()=>{m.value&&(e.editorOption=g(defaultOptions,t.options),e.editorOption.readOnly=!!t.disabled,e.quill=new Quill(m.value,e.editorOption),t.value&&e.quill.pasteHTML(t.value),e.quill.on("selection-change",u=>{u?d.emit("focus",e.quill):d.emit("blur",e.quill)}),e.quill.on("text-change",()=>{t.disabled&&e.quill.enable(!1);let u=m.value.children[0].innerHTML;const r=e.quill,f=e.quill.getText();u==="


"&&(u=""),h=u,d.emit("update:value",h),d.emit("change",{html:u,text:f,quill:r})}),d.emit("ready",e.quill))};return require$$0$1.onBeforeUnmount(()=>{const u=m.value.previousSibling;u&&u.className.indexOf("ql-toolbar")>-1&&u.parentNode.removeChild(u)}),require$$0$1.onMounted(()=>{a()}),require$$0$1.onUnmounted(()=>{e.quill=null}),{editor:m}}},_hoisted_1$x={ref:"editor"};function _sfc_render$2S(t,d,e,h,m,g){return require$$0$1.openBlock(),require$$0$1.createElementBlock("section",_hoisted_1$x,null,512)}var quillEditor=_export_sfc$1(_sfc_main$2S,[["render",_sfc_render$2S]]);quillEditor.install=function(t){t.component(quillEditor.name,quillEditor)};var richEditorWidget_vue_vue_type_style_index_0_scoped_true_lang="";const _sfc_main$2R={name:"rich-editor-widget",componentName:"FieldWidget",mixins:[emitter,fieldMixin,i18n$1],props:{field:Object,parentWidget:Object,parentList:Array,indexOfParentList:Number,designer:Object,designState:{type:Boolean,default:!1},subFormRowIndex:{type:Number,default:-1},subFormColIndex:{type:Number,default:-1},subFormRowId:{type:String,default:""}},components:{FormItemWrapper,quillEditor},data(){return{oldFieldValue:null,fieldModel:null,rules:[],customToolbar:[],valueChangedFlag:!1}},computed:{editorOption(){return{placeholder:this.field.options.placeholder,modules:{}}}},beforeCreate(){},created(){this.initFieldModel(),this.registerToRefList(),this.initEventHandler(),this.buildFieldRules(),this.handleOnCreated()},mounted(){this.handleOnMounted()},beforeUnmount(){this.unregisterFromRefList()},methods:{handleRichEditorChangeEvent(){this.valueChangedFlag=!0,this.syncUpdateFormModel(this.fieldModel)},handleRichEditorFocusEvent(){this.oldFieldValue=deepClone(this.fieldModel)},handleRichEditorBlurEvent(){this.valueChangedFlag&&(this.emitFieldDataChange(this.fieldModel,this.oldFieldValue),this.valueChangedFlag=!1)}}};function _sfc_render$2R(t,d,e,h,m,g){const a=require$$0$1.resolveComponent("quill-editor"),u=require$$0$1.resolveComponent("form-item-wrapper");return require$$0$1.openBlock(),require$$0$1.createBlock(u,{designer:e.designer,field:e.field,rules:m.rules,"design-state":e.designState,"parent-widget":e.parentWidget,"parent-list":e.parentList,"index-of-parent-list":e.indexOfParentList,"sub-form-row-index":e.subFormRowIndex,"sub-form-col-index":e.subFormColIndex,"sub-form-row-id":e.subFormRowId},{default:require$$0$1.withCtx(()=>[require$$0$1.createElementVNode("div",null,[require$$0$1.createVNode(a,{value:m.fieldModel,"onUpdate:value":d[0]||(d[0]=r=>m.fieldModel=r),options:g.editorOption,disabled:e.field.options.disabled,onBlur:g.handleRichEditorBlurEvent,onFocus:g.handleRichEditorFocusEvent,onChange:g.handleRichEditorChangeEvent,style:require$$0$1.normalizeStyle(e.field.options.contentHeight?`height: ${e.field.options.contentHeight};`:"")},null,8,["value","options","disabled","onBlur","onFocus","onChange","style"])])]),_:1},8,["designer","field","rules","design-state","parent-widget","parent-list","index-of-parent-list","sub-form-row-index","sub-form-col-index","sub-form-row-id"])}var richEditorWidget=_export_sfc$1(_sfc_main$2R,[["render",_sfc_render$2R],["__scopeId","data-v-a23436fa"]]),__glob_0_15$1=Object.freeze(Object.defineProperty({__proto__:null,default:richEditorWidget},Symbol.toStringTag,{value:"Module"})),selectWidget_vue_vue_type_style_index_0_scoped_true_lang="";const _sfc_main$2Q={name:"select-widget",componentName:"FieldWidget",mixins:[emitter,fieldMixin,i18n$1],props:{field:Object,parentWidget:Object,parentList:Array,indexOfParentList:Number,designer:Object,designState:{type:Boolean,default:!1},subFormRowIndex:{type:Number,default:-1},subFormColIndex:{type:Number,default:-1},subFormRowId:{type:String,default:""}},components:{FormItemWrapper},data(){return{oldFieldValue:null,fieldModel:null,rules:[]}},computed:{allowDefaultFirstOption(){return!!this.field.options.filterable&&!!this.field.options.allowCreate},remoteMethod(){if(!!this.field.options.remote&&!!this.field.options.onRemoteQuery)return this.remoteQuery}},beforeCreate(){},created(){this.initOptionItems(),this.initFieldModel(),this.registerToRefList(),this.initEventHandler(),this.buildFieldRules(),this.handleOnCreated()},mounted(){this.handleOnMounted()},beforeUnmount(){this.unregisterFromRefList()},methods:{}};function _sfc_render$2Q(t,d,e,h,m,g){const a=require$$0$1.resolveComponent("el-option"),u=require$$0$1.resolveComponent("el-select"),r=require$$0$1.resolveComponent("form-item-wrapper");return require$$0$1.openBlock(),require$$0$1.createBlock(r,{designer:e.designer,field:e.field,rules:m.rules,"design-state":e.designState,"parent-widget":e.parentWidget,"parent-list":e.parentList,"index-of-parent-list":e.indexOfParentList,"sub-form-row-index":e.subFormRowIndex,"sub-form-col-index":e.subFormColIndex,"sub-form-row-id":e.subFormRowId},{default:require$$0$1.withCtx(()=>[require$$0$1.createVNode(u,{ref:"fieldEditor",modelValue:m.fieldModel,"onUpdate:modelValue":d[0]||(d[0]=f=>m.fieldModel=f),class:"full-width-input",disabled:e.field.options.disabled,size:t.widgetSize,clearable:e.field.options.clearable,filterable:e.field.options.filterable,"allow-create":e.field.options.allowCreate,"default-first-option":g.allowDefaultFirstOption,"automatic-dropdown":e.field.options.automaticDropdown,multiple:e.field.options.multiple,"multiple-limit":e.field.options.multipleLimit,placeholder:e.field.options.placeholder||t.i18nt("render.hint.selectPlaceholder"),remote:e.field.options.remote,"remote-method":g.remoteMethod,onFocus:t.handleFocusCustomEvent,onBlur:t.handleBlurCustomEvent,onChange:t.handleChangeEvent},{default:require$$0$1.withCtx(()=>[(require$$0$1.openBlock(!0),require$$0$1.createElementBlock(require$$0$1.Fragment,null,require$$0$1.renderList(e.field.options.optionItems,f=>(require$$0$1.openBlock(),require$$0$1.createBlock(a,{key:f.value,label:f.label,value:f.value,disabled:f.disabled},null,8,["label","value","disabled"]))),128))]),_:1},8,["modelValue","disabled","size","clearable","filterable","allow-create","default-first-option","automatic-dropdown","multiple","multiple-limit","placeholder","remote","remote-method","onFocus","onBlur","onChange"])]),_:1},8,["designer","field","rules","design-state","parent-widget","parent-list","index-of-parent-list","sub-form-row-index","sub-form-col-index","sub-form-row-id"])}var selectWidget=_export_sfc$1(_sfc_main$2Q,[["render",_sfc_render$2Q],["__scopeId","data-v-038816bf"]]),__glob_0_16$1=Object.freeze(Object.defineProperty({__proto__:null,default:selectWidget},Symbol.toStringTag,{value:"Module"})),sliderWidget_vue_vue_type_style_index_0_scoped_true_lang="";const _sfc_main$2P={name:"slider-widget",componentName:"FieldWidget",mixins:[emitter,fieldMixin,i18n$1],props:{field:Object,parentWidget:Object,parentList:Array,indexOfParentList:Number,designer:Object,designState:{type:Boolean,default:!1},subFormRowIndex:{type:Number,default:-1},subFormColIndex:{type:Number,default:-1},subFormRowId:{type:String,default:""}},components:{FormItemWrapper},data(){return{oldFieldValue:null,fieldModel:null,rules:[]}},computed:{},beforeCreate(){},created(){this.initFieldModel(),this.registerToRefList(),this.initEventHandler(),this.buildFieldRules(),this.handleOnCreated()},mounted(){this.handleOnMounted()},beforeUnmount(){this.unregisterFromRefList()},methods:{}};function _sfc_render$2P(t,d,e,h,m,g){const a=require$$0$1.resolveComponent("el-slider"),u=require$$0$1.resolveComponent("form-item-wrapper");return require$$0$1.openBlock(),require$$0$1.createBlock(u,{designer:e.designer,field:e.field,rules:m.rules,"design-state":e.designState,"parent-widget":e.parentWidget,"parent-list":e.parentList,"index-of-parent-list":e.indexOfParentList,"sub-form-row-index":e.subFormRowIndex,"sub-form-col-index":e.subFormColIndex,"sub-form-row-id":e.subFormRowId},{default:require$$0$1.withCtx(()=>[require$$0$1.createVNode(a,{ref:"fieldEditor",modelValue:m.fieldModel,"onUpdate:modelValue":d[0]||(d[0]=r=>m.fieldModel=r),disabled:e.field.options.disabled,"show-stops":e.field.options.showStops,min:e.field.options.min,max:e.field.options.max,step:e.field.options.step,range:e.field.options.range,vertical:e.field.options.vertical,onChange:t.handleChangeEvent},null,8,["modelValue","disabled","show-stops","min","max","step","range","vertical","onChange"])]),_:1},8,["designer","field","rules","design-state","parent-widget","parent-list","index-of-parent-list","sub-form-row-index","sub-form-col-index","sub-form-row-id"])}var sliderWidget=_export_sfc$1(_sfc_main$2P,[["render",_sfc_render$2P],["__scopeId","data-v-92a76556"]]),__glob_0_17$1=Object.freeze(Object.defineProperty({__proto__:null,default:sliderWidget},Symbol.toStringTag,{value:"Module"})),slotWidget_vue_vue_type_style_index_0_scoped_true_lang="";const _sfc_main$2O={name:"slot-widget",componentName:"FieldWidget",mixins:[emitter,fieldMixin,i18n$1],props:{field:Object,parentWidget:Object,parentList:Array,indexOfParentList:Number,designer:Object,designState:{type:Boolean,default:!1},subFormRowIndex:{type:Number,default:-1},subFormColIndex:{type:Number,default:-1},subFormRowId:{type:String,default:""}},components:{StaticContentWrapper},computed:{},beforeCreate(){},created(){this.registerToRefList(),this.initEventHandler(),this.handleOnCreated()},mounted(){this.handleOnMounted()},beforeUnmount(){this.unregisterFromRefList()},methods:{}},_hoisted_1$w={key:0,class:"slot-title"};function _sfc_render$2O(t,d,e,h,m,g){const a=require$$0$1.resolveComponent("static-content-wrapper");return require$$0$1.openBlock(),require$$0$1.createBlock(a,{designer:e.designer,field:e.field,"design-state":e.designState,"parent-widget":e.parentWidget,"parent-list":e.parentList,"index-of-parent-list":e.indexOfParentList,"sub-form-row-index":e.subFormRowIndex,"sub-form-col-index":e.subFormColIndex,"sub-form-row-id":e.subFormRowId},{default:require$$0$1.withCtx(()=>[require$$0$1.createElementVNode("div",{class:require$$0$1.normalizeClass([e.designState?"slot-wrapper-design":"slot-wrapper-render"])},[require$$0$1.renderSlot(t.$slots,e.field.options.name,{formModel:t.formModel},void 0,!0),e.designState?(require$$0$1.openBlock(),require$$0$1.createElementBlock("div",_hoisted_1$w,require$$0$1.toDisplayString(e.field.options.label),1)):require$$0$1.createCommentVNode("",!0)],2)]),_:3},8,["designer","field","design-state","parent-widget","parent-list","index-of-parent-list","sub-form-row-index","sub-form-col-index","sub-form-row-id"])}var slotWidget=_export_sfc$1(_sfc_main$2O,[["render",_sfc_render$2O],["__scopeId","data-v-95f13fca"]]),__glob_0_18$1=Object.freeze(Object.defineProperty({__proto__:null,default:slotWidget},Symbol.toStringTag,{value:"Module"})),staticTextWidget_vue_vue_type_style_index_0_scoped_true_lang="";const _sfc_main$2N={name:"static-text-widget",componentName:"FieldWidget",mixins:[emitter,fieldMixin,i18n$1],props:{field:Object,parentWidget:Object,parentList:Array,indexOfParentList:Number,designer:Object,designState:{type:Boolean,default:!1},subFormRowIndex:{type:Number,default:-1},subFormColIndex:{type:Number,default:-1},subFormRowId:{type:String,default:""}},components:{StaticContentWrapper},computed:{},beforeCreate(){},created(){this.registerToRefList(),this.initEventHandler(),this.handleOnCreated()},mounted(){this.handleOnMounted()},beforeUnmount(){this.unregisterFromRefList()},methods:{}};function _sfc_render$2N(t,d,e,h,m,g){const a=require$$0$1.resolveComponent("static-content-wrapper");return require$$0$1.openBlock(),require$$0$1.createBlock(a,{designer:e.designer,field:e.field,"design-state":e.designState,"parent-widget":e.parentWidget,"parent-list":e.parentList,"index-of-parent-list":e.indexOfParentList,"sub-form-row-index":e.subFormRowIndex,"sub-form-col-index":e.subFormColIndex,"sub-form-row-id":e.subFormRowId},{default:require$$0$1.withCtx(()=>[require$$0$1.createElementVNode("div",{ref:"fieldEditor",style:require$$0$1.normalizeStyle(e.field.options.fontSize?`font-size: ${e.field.options.fontSize};`:"")},[require$$0$1.createElementVNode("pre",{style:require$$0$1.normalizeStyle({"white-space":e.field.options.preWrap?"pre-wrap":"pre","text-align":e.field.options.textAlign?e.field.options.textAlign:"left"})},require$$0$1.toDisplayString(e.field.options.textContent),5)],4)]),_:1},8,["designer","field","design-state","parent-widget","parent-list","index-of-parent-list","sub-form-row-index","sub-form-col-index","sub-form-row-id"])}var staticTextWidget=_export_sfc$1(_sfc_main$2N,[["render",_sfc_render$2N],["__scopeId","data-v-4071ab53"]]),__glob_0_20$1=Object.freeze(Object.defineProperty({__proto__:null,default:staticTextWidget},Symbol.toStringTag,{value:"Module"})),switchWidget_vue_vue_type_style_index_0_scoped_true_lang="";const _sfc_main$2M={name:"switch-widget",componentName:"FieldWidget",mixins:[emitter,fieldMixin,i18n$1],props:{field:Object,parentWidget:Object,parentList:Array,indexOfParentList:Number,designer:Object,designState:{type:Boolean,default:!1},subFormRowIndex:{type:Number,default:-1},subFormColIndex:{type:Number,default:-1},subFormRowId:{type:String,default:""}},components:{FormItemWrapper},data(){return{oldFieldValue:null,fieldModel:null,rules:[]}},computed:{},beforeCreate(){},created(){this.initFieldModel(),this.registerToRefList(),this.initEventHandler(),this.buildFieldRules(),this.handleOnCreated()},mounted(){this.handleOnMounted()},beforeUnmount(){this.unregisterFromRefList()},methods:{}};function _sfc_render$2M(t,d,e,h,m,g){const a=require$$0$1.resolveComponent("el-switch"),u=require$$0$1.resolveComponent("form-item-wrapper");return require$$0$1.openBlock(),require$$0$1.createBlock(u,{designer:e.designer,field:e.field,rules:m.rules,"design-state":e.designState,"parent-widget":e.parentWidget,"parent-list":e.parentList,"index-of-parent-list":e.indexOfParentList,"sub-form-row-index":e.subFormRowIndex,"sub-form-col-index":e.subFormColIndex,"sub-form-row-id":e.subFormRowId},{default:require$$0$1.withCtx(()=>[require$$0$1.createVNode(a,{ref:"fieldEditor",modelValue:m.fieldModel,"onUpdate:modelValue":d[0]||(d[0]=r=>m.fieldModel=r),disabled:e.field.options.disabled,"active-text":e.field.options.activeText,"inactive-text":e.field.options.inactiveText,"active-color":e.field.options.activeColor,"inactive-color":e.field.options.inactiveColor,width:e.field.options.switchWidth,onChange:t.handleChangeEvent},null,8,["modelValue","disabled","active-text","inactive-text","active-color","inactive-color","width","onChange"])]),_:1},8,["designer","field","rules","design-state","parent-widget","parent-list","index-of-parent-list","sub-form-row-index","sub-form-col-index","sub-form-row-id"])}var switchWidget=_export_sfc$1(_sfc_main$2M,[["render",_sfc_render$2M],["__scopeId","data-v-3529e848"]]),__glob_0_21$1=Object.freeze(Object.defineProperty({__proto__:null,default:switchWidget},Symbol.toStringTag,{value:"Module"})),textareaWidget_vue_vue_type_style_index_0_scoped_true_lang="";const _sfc_main$2L={name:"textarea-widget",componentName:"FieldWidget",mixins:[emitter,fieldMixin,i18n$1],props:{field:Object,parentWidget:Object,parentList:Array,indexOfParentList:Number,designer:Object,designState:{type:Boolean,default:!1},subFormRowIndex:{type:Number,default:-1},subFormColIndex:{type:Number,default:-1},subFormRowId:{type:String,default:""}},components:{FormItemWrapper},data(){return{oldFieldValue:null,fieldModel:null,rules:[]}},computed:{},beforeCreate(){},created(){this.initFieldModel(),this.registerToRefList(),this.initEventHandler(),this.buildFieldRules(),this.handleOnCreated()},mounted(){this.handleOnMounted()},beforeUnmount(){this.unregisterFromRefList()},methods:{}};function _sfc_render$2L(t,d,e,h,m,g){const a=require$$0$1.resolveComponent("el-input"),u=require$$0$1.resolveComponent("form-item-wrapper");return require$$0$1.openBlock(),require$$0$1.createBlock(u,{designer:e.designer,field:e.field,rules:m.rules,"design-state":e.designState,"parent-widget":e.parentWidget,"parent-list":e.parentList,"index-of-parent-list":e.indexOfParentList,"sub-form-row-index":e.subFormRowIndex,"sub-form-col-index":e.subFormColIndex,"sub-form-row-id":e.subFormRowId},{default:require$$0$1.withCtx(()=>[require$$0$1.createVNode(a,{type:"textarea",ref:"fieldEditor",modelValue:m.fieldModel,"onUpdate:modelValue":d[0]||(d[0]=r=>m.fieldModel=r),disabled:e.field.options.disabled,readonly:e.field.options.readonly,size:t.widgetSize,placeholder:e.field.options.placeholder,rows:e.field.options.rows,minlength:e.field.options.minLength,maxlength:e.field.options.maxLength,"show-word-limit":e.field.options.showWordLimit,onFocus:t.handleFocusCustomEvent,onBlur:t.handleBlurCustomEvent,onInput:t.handleInputCustomEvent,onChange:t.handleChangeEvent},null,8,["modelValue","disabled","readonly","size","placeholder","rows","minlength","maxlength","show-word-limit","onFocus","onBlur","onInput","onChange"])]),_:1},8,["designer","field","rules","design-state","parent-widget","parent-list","index-of-parent-list","sub-form-row-index","sub-form-col-index","sub-form-row-id"])}var textareaWidget=_export_sfc$1(_sfc_main$2L,[["render",_sfc_render$2L],["__scopeId","data-v-072d98c8"]]),__glob_0_22$1=Object.freeze(Object.defineProperty({__proto__:null,default:textareaWidget},Symbol.toStringTag,{value:"Module"})),timeRangeWidget_vue_vue_type_style_index_0_scoped_true_lang="";const _sfc_main$2K={name:"time-range-widget",componentName:"FieldWidget",mixins:[emitter,fieldMixin,i18n$1],props:{field:Object,parentWidget:Object,parentList:Array,indexOfParentList:Number,designer:Object,designState:{type:Boolean,default:!1},subFormRowIndex:{type:Number,default:-1},subFormColIndex:{type:Number,default:-1},subFormRowId:{type:String,default:""}},components:{FormItemWrapper},data(){return{oldFieldValue:null,fieldModel:null,rules:[]}},computed:{},beforeCreate(){},created(){this.initFieldModel(),this.registerToRefList(),this.initEventHandler(),this.buildFieldRules(),this.handleOnCreated()},mounted(){this.handleOnMounted()},beforeUnmount(){this.unregisterFromRefList()},methods:{}};function _sfc_render$2K(t,d,e,h,m,g){const a=require$$0$1.resolveComponent("el-time-picker"),u=require$$0$1.resolveComponent("form-item-wrapper");return require$$0$1.openBlock(),require$$0$1.createBlock(u,{designer:e.designer,field:e.field,rules:m.rules,"design-state":e.designState,"parent-widget":e.parentWidget,"parent-list":e.parentList,"index-of-parent-list":e.indexOfParentList,"sub-form-row-index":e.subFormRowIndex,"sub-form-col-index":e.subFormColIndex,"sub-form-row-id":e.subFormRowId},{default:require$$0$1.withCtx(()=>[require$$0$1.createElementVNode("div",{class:require$$0$1.normalizeClass([e.field.options.autoFullWidth?"auto-full-width":""])},[require$$0$1.createVNode(a,{ref:"fieldEditor","is-range":"",modelValue:m.fieldModel,"onUpdate:modelValue":d[0]||(d[0]=r=>m.fieldModel=r),class:require$$0$1.normalizeClass([e.field.options.autoFullWidth?"full-width-input":""]),disabled:e.field.options.disabled,readonly:e.field.options.readonly,size:t.widgetSize,clearable:e.field.options.clearable,editable:e.field.options.editable,format:e.field.options.format,"value-format":"HH:mm:ss","start-placeholder":e.field.options.startPlaceholder||t.i18nt("render.hint.startTimePlaceholder"),"end-placeholder":e.field.options.endPlaceholder||t.i18nt("render.hint.endTimePlaceholder"),onFocus:t.handleFocusCustomEvent,onBlur:t.handleBlurCustomEvent,onChange:t.handleChangeEvent},null,8,["modelValue","class","disabled","readonly","size","clearable","editable","format","start-placeholder","end-placeholder","onFocus","onBlur","onChange"])],2)]),_:1},8,["designer","field","rules","design-state","parent-widget","parent-list","index-of-parent-list","sub-form-row-index","sub-form-col-index","sub-form-row-id"])}var timeRangeWidget=_export_sfc$1(_sfc_main$2K,[["render",_sfc_render$2K],["__scopeId","data-v-60824824"]]),__glob_0_23$1=Object.freeze(Object.defineProperty({__proto__:null,default:timeRangeWidget},Symbol.toStringTag,{value:"Module"})),timeWidget_vue_vue_type_style_index_0_scoped_true_lang="";const _sfc_main$2J={name:"time-widget",componentName:"FieldWidget",mixins:[emitter,fieldMixin,i18n$1],props:{field:Object,parentWidget:Object,parentList:Array,indexOfParentList:Number,designer:Object,designState:{type:Boolean,default:!1},subFormRowIndex:{type:Number,default:-1},subFormColIndex:{type:Number,default:-1},subFormRowId:{type:String,default:""}},components:{FormItemWrapper},data(){return{oldFieldValue:null,fieldModel:null,rules:[]}},computed:{},beforeCreate(){},created(){this.initFieldModel(),this.registerToRefList(),this.initEventHandler(),this.buildFieldRules(),this.handleOnCreated()},mounted(){this.handleOnMounted()},beforeUnmount(){this.unregisterFromRefList()},methods:{}};function _sfc_render$2J(t,d,e,h,m,g){const a=require$$0$1.resolveComponent("el-time-picker"),u=require$$0$1.resolveComponent("form-item-wrapper");return require$$0$1.openBlock(),require$$0$1.createBlock(u,{designer:e.designer,field:e.field,rules:m.rules,"design-state":e.designState,"parent-widget":e.parentWidget,"parent-list":e.parentList,"index-of-parent-list":e.indexOfParentList,"sub-form-row-index":e.subFormRowIndex,"sub-form-col-index":e.subFormColIndex,"sub-form-row-id":e.subFormRowId},{default:require$$0$1.withCtx(()=>[require$$0$1.createVNode(a,{ref:"fieldEditor",modelValue:m.fieldModel,"onUpdate:modelValue":d[0]||(d[0]=r=>m.fieldModel=r),class:require$$0$1.normalizeClass([e.field.options.autoFullWidth?"auto-full-width":""]),disabled:e.field.options.disabled,readonly:e.field.options.readonly,size:t.widgetSize,clearable:e.field.options.clearable,editable:e.field.options.editable,format:e.field.options.format,"value-format":"HH:mm:ss",placeholder:e.field.options.placeholder||t.i18nt("render.hint.timePlaceholder"),onFocus:t.handleFocusCustomEvent,onBlur:t.handleBlurCustomEvent,onChange:t.handleChangeEvent},null,8,["modelValue","class","disabled","readonly","size","clearable","editable","format","placeholder","onFocus","onBlur","onChange"])]),_:1},8,["designer","field","rules","design-state","parent-widget","parent-list","index-of-parent-list","sub-form-row-index","sub-form-col-index","sub-form-row-id"])}var timeWidget=_export_sfc$1(_sfc_main$2J,[["render",_sfc_render$2J],["__scopeId","data-v-417e0c7c"]]),__glob_0_24$1=Object.freeze(Object.defineProperty({__proto__:null,default:timeWidget},Symbol.toStringTag,{value:"Module"}));let comps$1={};const modules$3={"./button-widget.vue":__glob_0_0$2,"./cascader-widget.vue":__glob_0_1$3,"./checkbox-widget.vue":__glob_0_2$3,"./color-widget.vue":__glob_0_3$3,"./date-range-widget.vue":__glob_0_4$3,"./date-widget.vue":__glob_0_5$3,"./divider-widget.vue":__glob_0_6$2,"./file-upload-widget.vue":__glob_0_7$1,"./form-item-wrapper.vue":__glob_0_8$1,"./html-text-widget.vue":__glob_0_9$1,"./input-widget.vue":__glob_0_10$1,"./number-widget.vue":__glob_0_11$1,"./picture-upload-widget.vue":__glob_0_12$1,"./radio-widget.vue":__glob_0_13$1,"./rate-widget.vue":__glob_0_14$1,"./rich-editor-widget.vue":__glob_0_15$1,"./select-widget.vue":__glob_0_16$1,"./slider-widget.vue":__glob_0_17$1,"./slot-widget.vue":__glob_0_18$1,"./static-content-wrapper.vue":__glob_0_19$1,"./static-text-widget.vue":__glob_0_20$1,"./switch-widget.vue":__glob_0_21$1,"./textarea-widget.vue":__glob_0_22$1,"./time-range-widget.vue":__glob_0_23$1,"./time-widget.vue":__glob_0_24$1};for(const t in modules$3){let d=modules$3[t].default.name;comps$1[d]=modules$3[t].default}var gridColItem_vue_vue_type_style_index_0_scoped_true_lang="";const _sfc_main$2I={name:"GridColItem",componentName:"ContainerItem",mixins:[emitter,i18n$1,refMixin],components:Se({},comps$1),props:{widget:Object,parentWidget:Object,parentList:Array,indexOfParentList:Number,colHeight:{type:String,default:null}},inject:["refList","globalModel","getFormConfig","previewState"],data(){return{layoutProps:{span:this.widget.options.span,md:this.widget.options.md||12,sm:this.widget.options.sm||12,xs:this.widget.options.xs||12,offset:this.widget.options.offset||0,push:this.widget.options.push||0,pull:this.widget.options.pull||0}}},computed:{formConfig(){return this.getFormConfig()},customClass(){return this.widget.options.customClass||""},colHeightStyle(){return this.colHeight?{height:this.colHeight+"px"}:{}}},created(){this.initLayoutProps(),this.initRefList()},methods:{initLayoutProps(){if(this.widget.options.responsive)if(this.previewState){this.layoutProps.md=void 0,this.layoutProps.sm=void 0,this.layoutProps.xs=void 0;let t=this.formConfig.layoutType;t==="H5"?this.layoutProps.span=this.widget.options.xs||12:t==="Pad"?this.layoutProps.span=this.widget.options.sm||12:this.layoutProps.span=this.widget.options.md||12}else this.layoutProps.span=void 0;else this.layoutProps.md=void 0,this.layoutProps.sm=void 0,this.layoutProps.xs=void 0}}},_hoisted_1$v={class:"blank-cell"},_hoisted_2$m={class:"invisible-content"};function _sfc_render$2I(t,d,e,h,m,g){const a=require$$0$1.resolveComponent("el-col");return require$$0$1.withDirectives((require$$0$1.openBlock(),require$$0$1.createBlock(a,require$$0$1.mergeProps({class:["grid-cell",[g.customClass]]},m.layoutProps,{style:g.colHeightStyle,key:e.widget.id}),{default:require$$0$1.withCtx(()=>[!!e.widget.widgetList&&e.widget.widgetList.length>0?(require$$0$1.openBlock(!0),require$$0$1.createElementBlock(require$$0$1.Fragment,{key:0},require$$0$1.renderList(e.widget.widgetList,(u,r)=>(require$$0$1.openBlock(),require$$0$1.createElementBlock(require$$0$1.Fragment,null,[u.category==="container"?(require$$0$1.openBlock(),require$$0$1.createBlock(require$$0$1.resolveDynamicComponent(t.getComponentByContainer(u)),{widget:u,key:r,"parent-list":e.widget.widgetList,"index-of-parent-list":r,"parent-widget":e.widget},require$$0$1.createSlots({_:2},[require$$0$1.renderList(Object.keys(t.$slots),f=>({name:f,fn:require$$0$1.withCtx(l=>[require$$0$1.renderSlot(t.$slots,f,require$$0$1.normalizeProps(require$$0$1.guardReactiveProps(l)),void 0,!0)])}))]),1032,["widget","parent-list","index-of-parent-list","parent-widget"])):(require$$0$1.openBlock(),require$$0$1.createBlock(require$$0$1.resolveDynamicComponent(u.type+"-widget"),{field:u,designer:null,key:r,"parent-list":e.widget.widgetList,"index-of-parent-list":r,"parent-widget":e.widget},require$$0$1.createSlots({_:2},[require$$0$1.renderList(Object.keys(t.$slots),f=>({name:f,fn:require$$0$1.withCtx(l=>[require$$0$1.renderSlot(t.$slots,f,require$$0$1.normalizeProps(require$$0$1.guardReactiveProps(l)),void 0,!0)])}))]),1032,["field","parent-list","index-of-parent-list","parent-widget"]))],64))),256)):(require$$0$1.openBlock(),require$$0$1.createBlock(a,{key:1},{default:require$$0$1.withCtx(()=>[require$$0$1.createElementVNode("div",_hoisted_1$v,[require$$0$1.createElementVNode("span",_hoisted_2$m,require$$0$1.toDisplayString(t.i18nt("render.hint.blankCellContent")),1)])]),_:1}))]),_:3},16,["class","style"])),[[require$$0$1.vShow,!e.widget.options.hidden]])}var GridColItem=_export_sfc$1(_sfc_main$2I,[["render",_sfc_render$2I],["__scopeId","data-v-9332ab84"]]),__glob_0_1$2=Object.freeze(Object.defineProperty({__proto__:null,default:GridColItem},Symbol.toStringTag,{value:"Module"})),containerItemMixin={inject:["getFormConfig","getGlobalDsv"],computed:{customClass(){return this.widget.options.customClass||""},formModel:{cache:!1,get(){return this.globalModel.formModel}}},mounted(){this.callSetHidden()},methods:{unregisterFromRefList(){if(this.refList!==null&&!!this.widget.options.name){let t=this.widget.options.name;delete this.refList[t]}},callSetHidden(){this.widget.options.hidden===!0&&this.setHidden(!0)},setHidden(t){this.widget.options.hidden=t;let d=e=>{let h=e.options.name,m=this.getWidgetRef(h);t&&!!m&&!!m.clearFieldRules&&m.clearFieldRules(),!t&&!!m&&!!m.buildFieldRules&&m.buildFieldRules()};traverseFieldWidgetsOfContainer(this.widget,d)},activeTab(t){t>=0&&t{d.options.active=e===t,e===t&&(this.activeTabName=d.options.name)})},disableTab(t){t>=0&&t=0&&t=0&&t=0&&t{let e=d.options.name+"@row"+this.rowIdData[t],h=this.getWidgetRef(e);h&&h.setDisabled(!0)})},enableSubFormRow(t){this.widget.widgetList.forEach(d=>{let e=d.options.name+"@row"+this.rowIdData[t],h=this.getWidgetRef(e);h&&h.setDisabled(!1)})},disableSubForm(){this.rowIdData.length>0&&this.rowIdData.forEach((t,d)=>{this.disableSubFormRow(d)}),this.actionDisabled=!0},enableSubForm(){this.rowIdData.length>0&&this.rowIdData.forEach((t,d)=>{this.enableSubFormRow(d)}),this.actionDisabled=!1},resetSubForm(){if(this.widget.type==="sub-form"){let t=this.formModel[this.widget.options.name];t&&(t.splice(0,t.length),this.rowIdData.splice(0,this.rowIdData.length)),this.widget.options.showBlankRow&&this.addSubFormRow()}},getSubFormValues(t=!0){if(this.widget.type==="sub-form")return this.formModel[this.widget.options.name];this.$message.error(this.i18nt("render.hint.nonSubFormType"))},addCssClass(t){this.widget.options.customClass?this.widget.options.customClass.push(t):this.widget.options.customClass=[t]},removeCssClass(t){if(!this.widget.options.customClass)return;let d=-1;this.widget.options.customClass.map((e,h)=>{e===t&&(d=h)}),d>-1&&this.widget.options.customClass.splice(d,1)}}};const _sfc_main$2H={name:"vf-grid-item",componentName:"ContainerItem",mixins:[emitter,i18n$1,refMixin,containerItemMixin],components:{ContainerItemWrapper,GridColItem},props:{widget:Object},inject:["refList","sfRefList","globalModel"],created(){this.initRefList()},mounted(){},beforeUnmount(){this.unregisterFromRefList()},methods:{}};function _sfc_render$2H(t,d,e,h,m,g){const a=require$$0$1.resolveComponent("grid-col-item"),u=require$$0$1.resolveComponent("el-row"),r=require$$0$1.resolveComponent("container-item-wrapper");return require$$0$1.openBlock(),require$$0$1.createBlock(r,{widget:e.widget},{default:require$$0$1.withCtx(()=>[require$$0$1.withDirectives((require$$0$1.openBlock(),require$$0$1.createBlock(u,{key:e.widget.id,gutter:e.widget.options.gutter,class:require$$0$1.normalizeClass(["grid-container",[t.customClass]]),ref:e.widget.id},{default:require$$0$1.withCtx(()=>[(require$$0$1.openBlock(!0),require$$0$1.createElementBlock(require$$0$1.Fragment,null,require$$0$1.renderList(e.widget.cols,(f,l)=>(require$$0$1.openBlock(),require$$0$1.createBlock(a,{key:l,widget:f,"parent-list":e.widget.cols,"index-of-parent-list":l,"parent-widget":e.widget,"col-height":e.widget.options.colHeight},require$$0$1.createSlots({_:2},[require$$0$1.renderList(Object.keys(t.$slots),n=>({name:n,fn:require$$0$1.withCtx(i=>[require$$0$1.renderSlot(t.$slots,n,require$$0$1.normalizeProps(require$$0$1.guardReactiveProps(i)))])}))]),1032,["widget","parent-list","index-of-parent-list","parent-widget","col-height"]))),128))]),_:3},8,["gutter","class"])),[[require$$0$1.vShow,!e.widget.options.hidden]])]),_:3},8,["widget"])}var gridItem=_export_sfc$1(_sfc_main$2H,[["render",_sfc_render$2H]]),__glob_0_2$2=Object.freeze(Object.defineProperty({__proto__:null,default:gridItem},Symbol.toStringTag,{value:"Module"})),subFormItem_vue_vue_type_style_index_0_scoped_true_lang="";const _sfc_main$2G={name:"sub-form-item",componentName:"ContainerItem",mixins:[emitter,i18n$1,refMixin,containerItemMixin],components:ke(Se({ContainerItemWrapper},comps$1),{SvgIcon}),props:{widget:Object},inject:["refList","sfRefList","globalModel"],data(){return{rowIdData:[],fieldSchemaData:[],actionDisabled:!1}},created(){this.initRefList(),this.registerSubFormToRefList(),this.initRowIdData(!0),this.initFieldSchemaData(),this.initEventHandler()},mounted(){this.handleSubFormFirstRowAdd()},beforeUnmount(){this.unregisterFromRefList()},methods:{getLabelAlign(t,d){return d.options.labelAlign||t.options.labelAlign},registerSubFormToRefList(){this.widget.type==="sub-form"&&(this.sfRefList[this.widget.options.name]=this)},initRowIdData(t){if(this.widget.type==="sub-form"){this.rowIdData.splice(0,this.rowIdData.length);let d=this.formModel[this.widget.options.name];!!d&&d.length>0&&(d.forEach(()=>{this.rowIdData.push("id"+generateId())}),t&&setTimeout(()=>{this.handleSubFormRowChange(d)},800))}},addToRowIdData(){this.rowIdData.push("id"+generateId())},insertToRowIdData(t){this.rowIdData.splice(t,0,"id"+generateId())},deleteFromRowIdData(t){this.rowIdData.splice(t,1)},getRowIdData(){return this.rowIdData},getWidgetRefOfSubForm(t,d){let e=t+"@row"+this.rowIdData[d];return this.getWidgetRef(e)},initFieldSchemaData(){if(this.widget.type!=="sub-form")return;let t=this.rowIdData.length;if(this.fieldSchemaData.splice(0,this.fieldSchemaData.length),t>0)for(let d=0;d{e.push(this.cloneFieldSchema(h))}),this.fieldSchemaData.push(e)}},addToFieldSchemaData(t){let d=[];this.widget.widgetList.forEach(e=>{d.push(this.cloneFieldSchema(e))}),t===void 0?this.fieldSchemaData.push(d):this.fieldSchemaData.splice(t,0,d)},deleteFromFieldSchemaData(t){this.fieldSchemaData.splice(t,1)},cloneFieldSchema(t){let d=deepClone(t);return d.id=t.type+generateId(),d},initEventHandler(){this.widget.type==="sub-form"&&this.on$("setFormData",t=>{this.initRowIdData(!1),this.initFieldSchemaData();let d=t[this.widget.options.name]||[];setTimeout(()=>{this.handleSubFormRowChange(d)},800)})},handleSubFormFirstRowAdd(){if(this.widget.type==="sub-form"&&!!this.widget.options.showBlankRow&&this.rowIdData.length===1){let t=this.formModel[this.widget.options.name]||[];this.handleSubFormRowAdd(t,this.rowIdData[0]),this.handleSubFormRowChange(t)}},addSubFormRow(){let t={};this.widget.widgetList.forEach(e=>{e.formItemFlag&&(t[e.options.name]=e.options.defaultValue)});let d=this.formModel[this.widget.options.name]||[];d.push(t),this.addToRowIdData(),this.addToFieldSchemaData(),this.handleSubFormRowAdd(d,this.rowIdData[d.length-1]),this.handleSubFormRowChange(d)},insertSubFormRow(t){let d={};this.widget.widgetList.forEach(h=>{h.formItemFlag&&(d[h.options.name]=h.options.defaultValue)});let e=this.formModel[this.widget.options.name]||[];e.splice(t,0,d),this.insertToRowIdData(t),this.addToFieldSchemaData(t),this.handleSubFormRowInsert(e,this.rowIdData[t]),this.handleSubFormRowChange(e)},deleteSubFormRow(t){this.$confirm(this.i18nt("render.hint.deleteSubFormRow")+"?",this.i18nt("render.hint.prompt"),{confirmButtonText:this.i18nt("render.hint.confirm"),cancelButtonText:this.i18nt("render.hint.cancel")}).then(()=>{let d=this.formModel[this.widget.options.name]||[],e=deepClone(d[t]);d.splice(t,1),this.deleteFromRowIdData(t),this.deleteFromFieldSchemaData(t),this.handleSubFormRowDelete(d,e),this.handleSubFormRowChange(d)}).catch(()=>{})},handleSubFormRowChange(t){this.widget.options.onSubFormRowChange&&new Function("subFormData",this.widget.options.onSubFormRowChange).call(this,t)},handleSubFormRowAdd(t,d){this.widget.options.onSubFormRowAdd&&new Function("subFormData","newRowId",this.widget.options.onSubFormRowAdd).call(this,t,d)},handleSubFormRowInsert(t,d){this.widget.options.onSubFormRowInsert&&new Function("subFormData","newRowId",this.widget.options.onSubFormRowInsert).call(this,t,d)},handleSubFormRowDelete(t,d){this.widget.options.onSubFormRowDelete&&new Function("subFormData","deletedDataRow",this.widget.options.onSubFormRowDelete).call(this,t,d)}}},_hoisted_1$u={class:"action-header-column"},_hoisted_2$l={class:"action-label"},_hoisted_3$h={key:0,class:"custom-label"},_hoisted_4$a=["title"],_hoisted_5$8={class:"sub-form-action-column hide-label"},_hoisted_6$7={class:"action-button-column"},_hoisted_7$4={key:0,class:"row-number-span"};function _sfc_render$2G(t,d,e,h,m,g){const a=require$$0$1.resolveComponent("svg-icon"),u=require$$0$1.resolveComponent("el-button"),r=require$$0$1.resolveComponent("el-tooltip"),f=require$$0$1.resolveComponent("el-row"),l=require$$0$1.resolveComponent("container-item-wrapper");return require$$0$1.openBlock(),require$$0$1.createBlock(l,{widget:e.widget},{default:require$$0$1.withCtx(()=>[require$$0$1.withDirectives((require$$0$1.openBlock(),require$$0$1.createElementBlock("div",{key:e.widget.id,class:"sub-form-container"},[require$$0$1.createVNode(f,{class:"header-row"},{default:require$$0$1.withCtx(()=>[require$$0$1.createElementVNode("div",_hoisted_1$u,[require$$0$1.createElementVNode("span",_hoisted_2$l,require$$0$1.toDisplayString(t.i18nt("render.hint.subFormAction")),1),require$$0$1.createVNode(u,{disabled:m.actionDisabled,round:"",type:"primary",size:"small",class:"action-button",onClick:g.addSubFormRow,title:t.i18nt("render.hint.subFormAddActionHint")},{default:require$$0$1.withCtx(()=>[require$$0$1.createTextVNode(require$$0$1.toDisplayString(t.i18nt("render.hint.subFormAddAction")),1),require$$0$1.createVNode(a,{"icon-class":"el-plus"})]),_:1},8,["disabled","onClick","title"])]),(require$$0$1.openBlock(!0),require$$0$1.createElementBlock(require$$0$1.Fragment,null,require$$0$1.renderList(e.widget.widgetList,n=>(require$$0$1.openBlock(),require$$0$1.createElementBlock("div",{key:n.id+"thc",class:require$$0$1.normalizeClass(["field-header-column",[g.getLabelAlign(e.widget,n),n.options.required?"is-required":""]]),style:require$$0$1.normalizeStyle({width:n.options.columnWidth})},[n.options.labelIconClass?(require$$0$1.openBlock(),require$$0$1.createElementBlock("span",_hoisted_3$h,[n.options.labelIconPosition==="front"?(require$$0$1.openBlock(),require$$0$1.createElementBlock(require$$0$1.Fragment,{key:0},[n.options.labelTooltip?(require$$0$1.openBlock(),require$$0$1.createElementBlock(require$$0$1.Fragment,{key:0},[require$$0$1.createVNode(r,{content:n.options.labelTooltip,effect:"light"},{default:require$$0$1.withCtx(()=>[require$$0$1.createVNode(a,{"icon-class":n.options.labelIconClass},null,8,["icon-class"])]),_:2},1032,["content"]),require$$0$1.createTextVNode(require$$0$1.toDisplayString(n.options.label),1)],64)):(require$$0$1.openBlock(),require$$0$1.createElementBlock(require$$0$1.Fragment,{key:1},[require$$0$1.createVNode(a,{"icon-class":n.options.labelIconClass},null,8,["icon-class"]),require$$0$1.createTextVNode(require$$0$1.toDisplayString(n.options.label),1)],64))],64)):n.options.labelIconPosition==="rear"?(require$$0$1.openBlock(),require$$0$1.createElementBlock(require$$0$1.Fragment,{key:1},[n.options.labelTooltip?(require$$0$1.openBlock(),require$$0$1.createElementBlock(require$$0$1.Fragment,{key:0},[require$$0$1.createTextVNode(require$$0$1.toDisplayString(n.options.label),1),require$$0$1.createVNode(r,{content:n.options.labelTooltip,effect:"light"},{default:require$$0$1.withCtx(()=>[require$$0$1.createVNode(a,{"icon-class":n.options.labelIconClass},null,8,["icon-class"])]),_:2},1032,["content"])],64)):(require$$0$1.openBlock(),require$$0$1.createElementBlock(require$$0$1.Fragment,{key:1},[require$$0$1.createTextVNode(require$$0$1.toDisplayString(n.options.label),1),require$$0$1.createVNode(a,{"icon-class":n.options.labelIconClass},null,8,["icon-class"])],64))],64)):require$$0$1.createCommentVNode("",!0)])):(require$$0$1.openBlock(),require$$0$1.createElementBlock("span",{key:1,title:n.options.labelTooltip},require$$0$1.toDisplayString(n.options.label),9,_hoisted_4$a))],6))),128))]),_:1}),(require$$0$1.openBlock(!0),require$$0$1.createElementBlock(require$$0$1.Fragment,null,require$$0$1.renderList(m.rowIdData,(n,i)=>(require$$0$1.openBlock(),require$$0$1.createBlock(f,{class:"sub-form-row",key:n},{default:require$$0$1.withCtx(()=>[require$$0$1.createElementVNode("div",_hoisted_5$8,[require$$0$1.createElementVNode("div",_hoisted_6$7,[require$$0$1.createVNode(u,{disabled:m.actionDisabled,circle:"",onClick:o=>g.insertSubFormRow(i),title:t.i18nt("render.hint.insertSubFormRow")},{default:require$$0$1.withCtx(()=>[require$$0$1.createVNode(a,{"icon-class":"el-plus"})]),_:2},1032,["disabled","onClick","title"]),require$$0$1.createVNode(u,{disabled:m.actionDisabled,circle:"",onClick:o=>g.deleteSubFormRow(i),title:t.i18nt("render.hint.deleteSubFormRow")},{default:require$$0$1.withCtx(()=>[require$$0$1.createVNode(a,{"icon-class":"el-delete"})]),_:2},1032,["disabled","onClick","title"]),e.widget.options.showRowNumber?(require$$0$1.openBlock(),require$$0$1.createElementBlock("span",_hoisted_7$4,"#"+require$$0$1.toDisplayString(i+1),1)):require$$0$1.createCommentVNode("",!0)])]),(require$$0$1.openBlock(!0),require$$0$1.createElementBlock(require$$0$1.Fragment,null,require$$0$1.renderList(e.widget.widgetList,(o,s)=>(require$$0$1.openBlock(),require$$0$1.createElementBlock("div",{key:o.id+"tc"+n,class:"sub-form-table-column hide-label",style:require$$0$1.normalizeStyle({width:o.options.columnWidth})},[(require$$0$1.openBlock(),require$$0$1.createBlock(require$$0$1.resolveDynamicComponent(o.type+"-widget"),{field:m.fieldSchemaData[i][s],key:m.fieldSchemaData[i][s].id,"parent-list":e.widget.widgetList,"index-of-parent-list":s,"parent-widget":e.widget,"sub-form-row-id":n,"sub-form-row-index":i,"sub-form-col-index":s},null,8,["field","parent-list","index-of-parent-list","parent-widget","sub-form-row-id","sub-form-row-index","sub-form-col-index"]))],4))),128))]),_:2},1024))),128))])),[[require$$0$1.vShow,!e.widget.options.hidden]])]),_:1},8,["widget"])}var subFormItem=_export_sfc$1(_sfc_main$2G,[["render",_sfc_render$2G],["__scopeId","data-v-2eb559e6"]]),__glob_0_3$2=Object.freeze(Object.defineProperty({__proto__:null,default:subFormItem},Symbol.toStringTag,{value:"Module"}));const _sfc_main$2F={name:"tab-item",componentName:"ContainerItem",mixins:[emitter,i18n$1,refMixin,containerItemMixin],components:Se({ContainerItemWrapper},comps$1),props:{widget:Object},inject:["refList","sfRefList","globalModel"],data(){return{activeTabName:""}},computed:{visibleTabs(){return this.widget.tabs.filter(t=>!t.options.hidden)}},created(){this.initRefList()},mounted(){this.initActiveTab()},beforeUnmount(){this.unregisterFromRefList()},methods:{initActiveTab(){if(this.widget.type==="tab"&&this.widget.tabs.length>0){let t=this.widget.tabs.filter(d=>d.options.active===!0);t.length>0?this.activeTabName=t[0].options.name:this.activeTabName=this.widget.tabs[0].options.name}}}};function _sfc_render$2F(t,d,e,h,m,g){const a=require$$0$1.resolveComponent("el-tab-pane"),u=require$$0$1.resolveComponent("el-tabs"),r=require$$0$1.resolveComponent("container-item-wrapper");return require$$0$1.openBlock(),require$$0$1.createBlock(r,{widget:e.widget},{default:require$$0$1.withCtx(()=>[require$$0$1.withDirectives((require$$0$1.openBlock(),require$$0$1.createElementBlock("div",{key:e.widget.id,class:"tab-container"},[require$$0$1.createVNode(u,{modelValue:m.activeTabName,"onUpdate:modelValue":d[0]||(d[0]=f=>m.activeTabName=f),type:e.widget.displayType,ref:e.widget.id,class:require$$0$1.normalizeClass([t.customClass])},{default:require$$0$1.withCtx(()=>[(require$$0$1.openBlock(!0),require$$0$1.createElementBlock(require$$0$1.Fragment,null,require$$0$1.renderList(g.visibleTabs,(f,l)=>(require$$0$1.openBlock(),require$$0$1.createBlock(a,{key:l,label:f.options.label,disabled:f.options.disabled,name:f.options.name},{default:require$$0$1.withCtx(()=>[(require$$0$1.openBlock(!0),require$$0$1.createElementBlock(require$$0$1.Fragment,null,require$$0$1.renderList(f.widgetList,(n,i)=>(require$$0$1.openBlock(),require$$0$1.createElementBlock(require$$0$1.Fragment,null,[n.category==="container"?(require$$0$1.openBlock(),require$$0$1.createBlock(require$$0$1.resolveDynamicComponent(t.getComponentByContainer(n)),{widget:n,key:i,"parent-list":f.widgetList,"index-of-parent-list":i,"parent-widget":e.widget},require$$0$1.createSlots({_:2},[require$$0$1.renderList(Object.keys(t.$slots),o=>({name:o,fn:require$$0$1.withCtx(s=>[require$$0$1.renderSlot(t.$slots,o,require$$0$1.normalizeProps(require$$0$1.guardReactiveProps(s)))])}))]),1032,["widget","parent-list","index-of-parent-list","parent-widget"])):(require$$0$1.openBlock(),require$$0$1.createBlock(require$$0$1.resolveDynamicComponent(n.type+"-widget"),{field:n,key:i,"parent-list":f.widgetList,"index-of-parent-list":i,"parent-widget":e.widget},require$$0$1.createSlots({_:2},[require$$0$1.renderList(Object.keys(t.$slots),o=>({name:o,fn:require$$0$1.withCtx(s=>[require$$0$1.renderSlot(t.$slots,o,require$$0$1.normalizeProps(require$$0$1.guardReactiveProps(s)))])}))]),1032,["field","parent-list","index-of-parent-list","parent-widget"]))],64))),256))]),_:2},1032,["label","disabled","name"]))),128))]),_:3},8,["modelValue","type","class"])])),[[require$$0$1.vShow,!e.widget.options.hidden]])]),_:3},8,["widget"])}var tabItem=_export_sfc$1(_sfc_main$2F,[["render",_sfc_render$2F]]),__glob_0_4$2=Object.freeze(Object.defineProperty({__proto__:null,default:tabItem},Symbol.toStringTag,{value:"Module"})),tableCellItem_vue_vue_type_style_index_0_scoped_true_lang="";const _sfc_main$2E={name:"TableCellItem",componentName:"ContainerItem",mixins:[emitter,i18n$1,refMixin],components:Se({},comps$1),props:{widget:Object,rowIndex:Number,colIndex:Number},inject:["refList","globalModel"],computed:{customClass(){return this.widget.options.customClass||""}},created(){},methods:{}},_hoisted_1$t=["colspan","rowspan"];function _sfc_render$2E(t,d,e,h,m,g){return require$$0$1.openBlock(),require$$0$1.createElementBlock("td",{class:require$$0$1.normalizeClass(["table-cell",[g.customClass]]),colspan:e.widget.options.colspan||1,rowspan:e.widget.options.rowspan||1,style:require$$0$1.normalizeStyle({width:e.widget.options.cellWidth+" !important"||"",height:e.widget.options.cellHeight+" !important"||"","word-break":e.widget.options.wordBreak?"break-all":"normal"})},[(require$$0$1.openBlock(!0),require$$0$1.createElementBlock(require$$0$1.Fragment,null,require$$0$1.renderList(e.widget.widgetList,(a,u)=>(require$$0$1.openBlock(),require$$0$1.createElementBlock(require$$0$1.Fragment,null,[a.category==="container"?(require$$0$1.openBlock(),require$$0$1.createBlock(require$$0$1.resolveDynamicComponent(t.getComponentByContainer(a)),{widget:a,key:u,"parent-list":e.widget.widgetList,"index-of-parent-list":u,"parent-widget":e.widget},require$$0$1.createSlots({_:2},[require$$0$1.renderList(Object.keys(t.$slots),r=>({name:r,fn:require$$0$1.withCtx(f=>[require$$0$1.renderSlot(t.$slots,r,require$$0$1.normalizeProps(require$$0$1.guardReactiveProps(f)),void 0,!0)])}))]),1032,["widget","parent-list","index-of-parent-list","parent-widget"])):(require$$0$1.openBlock(),require$$0$1.createBlock(require$$0$1.resolveDynamicComponent(a.type+"-widget"),{field:a,key:u,"parent-list":e.widget.widgetList,"index-of-parent-list":u,"parent-widget":e.widget},require$$0$1.createSlots({_:2},[require$$0$1.renderList(Object.keys(t.$slots),r=>({name:r,fn:require$$0$1.withCtx(f=>[require$$0$1.renderSlot(t.$slots,r,require$$0$1.normalizeProps(require$$0$1.guardReactiveProps(f)),void 0,!0)])}))]),1032,["field","parent-list","index-of-parent-list","parent-widget"]))],64))),256))],14,_hoisted_1$t)}var TableCellItem=_export_sfc$1(_sfc_main$2E,[["render",_sfc_render$2E],["__scopeId","data-v-1825ed0b"]]),__glob_0_5$2=Object.freeze(Object.defineProperty({__proto__:null,default:TableCellItem},Symbol.toStringTag,{value:"Module"})),tableItem_vue_vue_type_style_index_0_scoped_true_lang="";const _sfc_main$2D={name:"table-item",componentName:"ContainerItem",mixins:[emitter,i18n$1,refMixin,containerItemMixin],components:{ContainerItemWrapper,TableCellItem},props:{widget:Object},inject:["refList","sfRefList","globalModel"],created(){this.initRefList()},mounted(){},beforeUnmount(){this.unregisterFromRefList()},methods:{}};function _sfc_render$2D(t,d,e,h,m,g){const a=require$$0$1.resolveComponent("table-cell-item"),u=require$$0$1.resolveComponent("container-item-wrapper");return require$$0$1.openBlock(),require$$0$1.createBlock(u,{widget:e.widget},{default:require$$0$1.withCtx(()=>[require$$0$1.withDirectives((require$$0$1.openBlock(),require$$0$1.createElementBlock("div",{key:e.widget.id,class:"table-container"},[require$$0$1.createElementVNode("table",{ref:e.widget.id,class:require$$0$1.normalizeClass(["table-layout",[t.customClass]])},[require$$0$1.createElementVNode("tbody",null,[(require$$0$1.openBlock(!0),require$$0$1.createElementBlock(require$$0$1.Fragment,null,require$$0$1.renderList(e.widget.rows,(r,f)=>(require$$0$1.openBlock(),require$$0$1.createElementBlock("tr",{key:r.id},[(require$$0$1.openBlock(!0),require$$0$1.createElementBlock(require$$0$1.Fragment,null,require$$0$1.renderList(r.cols,(l,n)=>(require$$0$1.openBlock(),require$$0$1.createElementBlock(require$$0$1.Fragment,null,[l.merged?require$$0$1.createCommentVNode("",!0):(require$$0$1.openBlock(),require$$0$1.createBlock(a,{widget:l,key:n,"parent-list":e.widget.cols,"row-index":f,"col-index":n,"parent-widget":e.widget},require$$0$1.createSlots({_:2},[require$$0$1.renderList(Object.keys(t.$slots),i=>({name:i,fn:require$$0$1.withCtx(o=>[require$$0$1.renderSlot(t.$slots,i,require$$0$1.normalizeProps(require$$0$1.guardReactiveProps(o)),void 0,!0)])}))]),1032,["widget","parent-list","row-index","col-index","parent-widget"]))],64))),256))]))),128))])],2)])),[[require$$0$1.vShow,!e.widget.options.hidden]])]),_:3},8,["widget"])}var tableItem=_export_sfc$1(_sfc_main$2D,[["render",_sfc_render$2D],["__scopeId","data-v-dfc6ca8e"]]),__glob_0_6$1=Object.freeze(Object.defineProperty({__proto__:null,default:tableItem},Symbol.toStringTag,{value:"Module"}));const modules$2={"./container-item-wrapper.vue":__glob_0_0$3,"./grid-col-item.vue":__glob_0_1$2,"./grid-item.vue":__glob_0_2$2,"./sub-form-item.vue":__glob_0_3$2,"./tab-item.vue":__glob_0_4$2,"./table-cell-item.vue":__glob_0_5$2,"./table-item.vue":__glob_0_6$1};var ContainerItems={install(t){for(const d in modules$2){let e=modules$2[d].default.name;t.component(e,modules$2[d].default)}}},index_vue_vue_type_style_index_0_scoped_true_lang$5="";const _sfc_main$2C={name:"VFormRender",componentName:"VFormRender",mixins:[emitter,i18n$1],components:Se({},comps$1),props:{formJson:{type:Object,default:()=>buildDefaultFormJson()},formData:{type:Object,default:()=>({})},optionData:{type:Object,default:()=>({})},previewState:{type:Boolean,default:!1},globalDsv:{type:Object,default:()=>({})}},provide(){return{refList:this.widgetRefList,sfRefList:this.subFormRefList,getFormConfig:()=>this.formJsonObj.formConfig,getGlobalDsv:()=>this.globalDsv,globalOptionData:this.optionData,getOptionData:()=>this.optionData,globalModel:{formModel:this.formDataModel},previewState:this.previewState}},data(){return{formJsonObj:this.formJson,formDataModel:{},widgetRefList:{},subFormRefList:{},formId:null,externalComponents:{}}},computed:{formConfig(){return this.formJsonObj.formConfig},widgetList(){return this.formJsonObj.widgetList},labelPosition(){return!!this.formConfig&&!!this.formConfig.labelPosition?this.formConfig.labelPosition:"left"},labelWidth(){return!!this.formConfig&&!!this.formConfig.labelWidth?this.formConfig.labelWidth+"px":"80px"},size(){return!!this.formConfig&&!!this.formConfig.size?this.formConfig.size:"default"},customClass(){return!!this.formConfig&&!!this.formConfig.customClass?this.formConfig.customClass:""}},watch:{},created(){this.buildFormModel(this.formJsonObj?this.formJsonObj.widgetList:null),this.initFormObject()},mounted(){this.initLocale(),this.handleOnMounted()},methods:{initFormObject(t=!0){this.formId="vfRender"+generateId(),t&&this.insertCustomStyleAndScriptNode(),this.addFieldChangeEventHandler(),this.addFieldValidateEventHandler(),this.registerFormToRefList(),this.handleOnCreated()},getContainerWidgetName(t){return t.type==="grid"?"vf-grid-item":t.type+"-item"},getWidgetName(t){return t.type+"-widget"},initLocale(){let t=localStorage.getItem("v_form_locale")||"zh-CN";this.changeLanguage(t)},insertCustomStyleAndScriptNode(){!!this.formConfig&&!!this.formConfig.cssCode&&insertCustomCssToHead(this.formConfig.cssCode,this.previewState?"":this.formId),!!this.formConfig&&!!this.formConfig.functions&&insertGlobalFunctionsToHtml(this.formConfig.functions,this.previewState?"":this.formId)},buildFormModel(t){!!t&&t.length>0&&t.forEach(d=>{this.buildDataFromWidget(d)})},buildDataFromWidget(t){if(t.category==="container")if(t.type==="grid")!!t.cols&&t.cols.length>0&&t.cols.forEach(d=>{this.buildDataFromWidget(d)});else if(t.type==="table")!!t.rows&&t.rows.length>0&&t.rows.forEach(d=>{!!d.cols&&d.cols.length>0&&d.cols.forEach(e=>{this.buildDataFromWidget(e)})});else if(t.type==="tab")!!t.tabs&&t.tabs.length>0&&t.tabs.forEach(d=>{!!d.widgetList&&d.widgetList.length>0&&d.widgetList.forEach(e=>{this.buildDataFromWidget(e)})});else if(t.type==="sub-form"){let d=t.options.name;if(this.formData.hasOwnProperty(d)){let e=this.formData[d];this.formDataModel[d]=deepClone(e)}else{let e={};t.options.showBlankRow?(t.widgetList.forEach(h=>{h.formItemFlag&&(e[h.options.name]=h.options.defaultValue)}),this.formDataModel[d]=[e]):this.formDataModel[d]=[]}}else t.type==="grid-col"||t.type==="table-cell"?!!t.widgetList&&t.widgetList.length>0&&t.widgetList.forEach(d=>{this.buildDataFromWidget(d)}):!!t.widgetList&&t.widgetList.length>0&&t.widgetList.forEach(d=>{this.buildDataFromWidget(d)});else if(t.formItemFlag)if(!this.formData.hasOwnProperty(t.options.name))this.formDataModel[t.options.name]=t.options.defaultValue;else{let d=this.formData[t.options.name];this.formDataModel[t.options.name]=deepClone(d)}},addFieldChangeEventHandler(){this.off$("fieldChange"),this.on$("fieldChange",(t,d,e,h,m)=>{this.handleFieldDataChange(t,d,e,h,m),this.$emit("formChange",t,d,e,this.formDataModel,h,m)})},addFieldValidateEventHandler(){this.off$("fieldValidation"),this.on$("fieldValidation",t=>{this.$refs.renderForm.validateField(t)})},registerFormToRefList(){this.widgetRefList.v_form_ref=this},handleFieldDataChange(t,d,e,h,m){!!this.formConfig&&!!this.formConfig.onFormDataChange&&new Function("fieldName","newValue","oldValue","formModel","subFormName","subFormRowIndex",this.formConfig.onFormDataChange).call(this,t,d,e,this.formDataModel,h,m)},handleOnCreated(){!!this.formConfig&&!!this.formConfig.onFormCreated&&new Function(this.formConfig.onFormCreated).call(this)},handleOnMounted(){!!this.formConfig&&!!this.formConfig.onFormMounted&&new Function(this.formConfig.onFormMounted).call(this)},findWidgetAndSetDisabled(t,d){let e=this.getWidgetRef(t);e?e.setDisabled(d):this.findWidgetOfSubFormAndSetDisabled(t,d)},findWidgetOfSubFormAndSetDisabled(t,d){this.findWidgetNameInSubForm(t).forEach(e=>{let h=this.getWidgetRef(e);h&&h.setDisabled(d)})},findWidgetAndSetHidden(t,d){let e=this.getWidgetRef(t);e?e.setHidden(d):this.findWidgetOfSubFormAndSetHidden(t,d)},findWidgetOfSubFormAndSetHidden(t,d){this.findWidgetNameInSubForm(t).forEach(e=>{let h=this.getWidgetRef(e);h&&h.setHidden(d)})},findWidgetNameInSubForm(t){let d=[],e=null,h=(m,g)=>{!!m.options&&m.options.name===t&&(e=g.options.name)};if(traverseFieldWidgets(this.widgetList,h),e){let m=this.getWidgetRef(e);if(m){let g=m.getRowIdData();!!g&&g.length>0&&g.forEach(a=>{d.push(t+"@row"+a)})}}return d},changeLanguage(t){changeLocale(t)},getNativeForm(){return this.$refs.renderForm},getFormRef(){return this},getWidgetRef(t,d=!1){let e=this.widgetRefList[t];return!e&&!!d&&this.$message.error(this.i18nt("render.hint.refNotFound")+t),e},clearFormDataModel(){for(let t in this.formDataModel)delete this.formDataModel[t]},setFormJson(t){if(t)if(typeof t=="string"||t.constructor===Object){let d=null;if(typeof t=="string"?d=JSON.parse(t):d=t,!d.formConfig||!d.widgetList){this.$message.error("Invalid format of form json.");return}this.clearFormDataModel(),this.buildFormModel(d.widgetList),this.formJsonObj.formConfig=d.formConfig,this.formJsonObj.widgetList=d.widgetList,this.insertCustomStyleAndScriptNode(),this.$nextTick(()=>{this.initFormObject(!1),this.handleOnMounted()})}else this.$message.error("Set form json failed.")},reloadOptionData(t){let d=[];!!t&&typeof t=="string"?d=[t]:!!t&&Array.isArray(t)&&(d=[...t]),this.broadcast("FieldWidget","reloadOptionItems",d)},getFormData(t=!0){if(!t)return this.formDataModel;let d=function(){},e=new window.Promise(function(h,m){d=function(g,a){a?m(a):h(g)}});return this.$refs.renderForm.validate(h=>{h?d(this.formDataModel):d(this.formDataModel,this.i18nt("render.hint.validationFailed"))}),e},setFormData(t){Object.keys(this.formDataModel).forEach(d=>{!!t&&t.hasOwnProperty(d)&&(this.formDataModel[d]=deepClone(t[d]))}),this.broadcast("ContainerItem","setFormData",this.formDataModel),this.broadcast("FieldWidget","setFormData",this.formDataModel)},getFieldValue(t){let d=this.getWidgetRef(t);if(!!d&&!!d.getValue)return d.getValue();if(!d){let e=[];return this.findWidgetNameInSubForm(t).forEach(h=>{let m=this.getWidgetRef(h);!!m&&!!m.getValue&&e.push(m.getValue())}),e}},setFieldValue(t,d){let e=this.getWidgetRef(t);!!e&&!!e.setValue&&e.setValue(d),e||this.findWidgetNameInSubForm(t).forEach(h=>{let m=this.getWidgetRef(h);!!m&&!!m.setValue&&m.setValue(d)})},getSubFormValues(t,d=!0){return this.subFormRefList[t].getSubFormValues(d)},disableForm(){Object.keys(this.widgetRefList).forEach(d=>{let e=this.getWidgetRef(d);if(e)if(!!e.widget&&e.widget.type==="sub-form")e.disableSubForm();else{//!!foundW.setDisabled && foundW.setDisabled(true) +e.setDisabled&&e.setDisabled(!0)}})},enableForm(){Object.keys(this.widgetRefList).forEach(d=>{let e=this.getWidgetRef(d);if(e)if(!!e.widget&&e.widget.type==="sub-form")e.enableSubForm();else{//!!foundW.setDisabled && foundW.setDisabled(false) +e.setDisabled&&e.setDisabled(!1)}})},resetForm(){Object.keys(this.subFormRefList).forEach(e=>{this.subFormRefList[e].resetSubForm&&this.subFormRefList[e].resetSubForm()}),Object.keys(this.widgetRefList).forEach(e=>{let h=this.getWidgetRef(e);!!h&&!h.subFormItemFlag&&!!h.resetField&&h.resetField()}),this.$nextTick(()=>{this.clearValidate()})},clearValidate(t){this.$refs.renderForm.clearValidate(t)},validateForm(t){this.$refs.renderForm.validate(d=>{t(d)})},validateFields(){},disableWidgets(t){t&&(typeof t=="string"?this.findWidgetAndSetDisabled(t,!0):Array.isArray(t)&&t.forEach(d=>{this.findWidgetAndSetDisabled(d,!0)}))},enableWidgets(t){t&&(typeof t=="string"?this.findWidgetAndSetDisabled(t,!1):Array.isArray(t)&&t.forEach(d=>{this.findWidgetAndSetDisabled(d,!1)}))},hideWidgets(t){t&&(typeof t=="string"?this.findWidgetAndSetHidden(t,!0):Array.isArray(t)&&t.forEach(d=>{this.findWidgetAndSetHidden(d,!0)}))},showWidgets(t){t&&(typeof t=="string"?this.findWidgetAndSetHidden(t,!1):Array.isArray(t)&&t.forEach(d=>{this.findWidgetAndSetHidden(d,!1)}))},getFieldWidgets(){return getAllFieldWidgets(this.formJsonObj.widgetList)},getContainerWidgets(){return getAllContainerWidgets(this.formJsonObj.widgetList)},addEC(t,d){this.externalComponents[t]=d},hasEC(t){return this.externalComponents.hasOwnProperty(t)},getEC(t){return this.externalComponents[t]},getGlobalDsv(){return this.globalDsv}}};function _sfc_render$2C(t,d,e,h,m,g){const a=require$$0$1.resolveComponent("el-form");return require$$0$1.openBlock(),require$$0$1.createBlock(a,{"label-position":g.labelPosition,size:g.size,class:require$$0$1.normalizeClass([[g.customClass],"render-form"]),"label-width":g.labelWidth,"validate-on-rule-change":!1,model:m.formDataModel,ref:"renderForm",onSubmit:d[0]||(d[0]=require$$0$1.withModifiers(()=>{},["prevent"]))},{default:require$$0$1.withCtx(()=>[(require$$0$1.openBlock(!0),require$$0$1.createElementBlock(require$$0$1.Fragment,null,require$$0$1.renderList(g.widgetList,(u,r)=>(require$$0$1.openBlock(),require$$0$1.createElementBlock(require$$0$1.Fragment,null,[u.category==="container"?(require$$0$1.openBlock(),require$$0$1.createBlock(require$$0$1.resolveDynamicComponent(g.getContainerWidgetName(u)),{widget:u,key:u.id,"parent-list":g.widgetList,"index-of-parent-list":r,"parent-widget":null},require$$0$1.createSlots({_:2},[require$$0$1.renderList(Object.keys(t.$slots),f=>({name:f,fn:require$$0$1.withCtx(l=>[require$$0$1.renderSlot(t.$slots,f,require$$0$1.normalizeProps(require$$0$1.guardReactiveProps(l)),void 0,!0)])}))]),1032,["widget","parent-list","index-of-parent-list"])):(require$$0$1.openBlock(),require$$0$1.createBlock(require$$0$1.resolveDynamicComponent(g.getWidgetName(u)),{field:u,"form-model":m.formDataModel,designer:null,key:u.id,"parent-list":g.widgetList,"index-of-parent-list":r,"parent-widget":null},require$$0$1.createSlots({_:2},[require$$0$1.renderList(Object.keys(t.$slots),f=>({name:f,fn:require$$0$1.withCtx(l=>[require$$0$1.renderSlot(t.$slots,f,require$$0$1.normalizeProps(require$$0$1.guardReactiveProps(l)),void 0,!0)])}))]),1032,["field","form-model","parent-list","index-of-parent-list"]))],64))),256))]),_:3},8,["label-position","size","class","label-width","model"])}var VFormRender=_export_sfc$1(_sfc_main$2C,[["render",_sfc_render$2C],["__scopeId","data-v-544703a2"]]),ace$2={exports:{}};(function(t,d){(function(){var e="ace",h=function(){return this}();!h&&typeof window!="undefined"&&(h=window);var m=function(l,n,i){if(typeof l!="string"){m.original?m.original.apply(this,arguments):(console.error("dropping module because define wasn't a string."),console.trace());return}arguments.length==2&&(i=n),m.modules[l]||(m.payloads[l]=i,m.modules[l]=null)};m.modules={},m.payloads={};var g=function(l,n,i){if(typeof n=="string"){var o=r(l,n);if(o!=null)return i&&i(),o}else if(Object.prototype.toString.call(n)==="[object Array]"){for(var s=[],c=0,p=n.length;cr.length)&&(u=r.length),u-=a.length;var f=r.indexOf(a,u);return f!==-1&&f===u}),String.prototype.repeat||g(String.prototype,"repeat",function(a){for(var u="",r=this;a>0;)a&1&&(u+=r),(a>>=1)&&(r+=r);return u}),String.prototype.includes||g(String.prototype,"includes",function(a,u){return this.indexOf(a,u)!=-1}),Object.assign||(Object.assign=function(a){if(a==null)throw new TypeError("Cannot convert undefined or null to object");for(var u=Object(a),r=1;r>>0,f=arguments[1],l=f>>0,n=l<0?Math.max(r+l,0):Math.min(l,r),i=arguments[2],o=i===void 0?r:i>>0,s=o<0?Math.max(r+o,0):Math.min(o,r);n0;)r&1&&(f+=u),(r>>=1)&&(u+=u);return f};var g=/^\s\s*/,a=/\s\s*$/;h.stringTrimLeft=function(u){return u.replace(g,"")},h.stringTrimRight=function(u){return u.replace(a,"")},h.copyObject=function(u){var r={};for(var f in u)r[f]=u[f];return r},h.copyArray=function(u){for(var r=[],f=0,l=u.length;f65535?2:1}}),ace.define("ace/lib/useragent",["require","exports","module"],function(e,h,m){h.OS={LINUX:"LINUX",MAC:"MAC",WINDOWS:"WINDOWS"},h.getOS=function(){return h.isMac?h.OS.MAC:h.isLinux?h.OS.LINUX:h.OS.WINDOWS};var g=typeof navigator=="object"?navigator:{},a=(/mac|win|linux/i.exec(g.platform)||["other"])[0].toLowerCase(),u=g.userAgent||"",r=g.appName||"";h.isWin=a=="win",h.isMac=a=="mac",h.isLinux=a=="linux",h.isIE=r=="Microsoft Internet Explorer"||r.indexOf("MSAppHost")>=0?parseFloat((u.match(/(?:MSIE |Trident\/[0-9]+[\.0-9]+;.*rv:)([0-9]+[\.0-9]+)/)||[])[1]):parseFloat((u.match(/(?:Trident\/[0-9]+[\.0-9]+;.*rv:)([0-9]+[\.0-9]+)/)||[])[1]),h.isOldIE=h.isIE&&h.isIE<9,h.isGecko=h.isMozilla=u.match(/ Gecko\/\d+/),h.isOpera=typeof opera=="object"&&Object.prototype.toString.call(window.opera)=="[object Opera]",h.isWebKit=parseFloat(u.split("WebKit/")[1])||void 0,h.isChrome=parseFloat(u.split(" Chrome/")[1])||void 0,h.isSafari=parseFloat(u.split(" Safari/")[1])&&!h.isChrome||void 0,h.isEdge=parseFloat(u.split(" Edge/")[1])||void 0,h.isAIR=u.indexOf("AdobeAIR")>=0,h.isAndroid=u.indexOf("Android")>=0,h.isChromeOS=u.indexOf(" CrOS ")>=0,h.isIOS=/iPad|iPhone|iPod/.test(u)&&!window.MSStream,h.isIOS&&(h.isMac=!0),h.isMobile=h.isIOS||h.isAndroid}),ace.define("ace/lib/dom",["require","exports","module","ace/lib/useragent"],function(e,h,m){var g=e("./useragent"),a="http://www.w3.org/1999/xhtml";h.buildDom=function i(o,s,c){if(typeof o=="string"&&o){var p=document.createTextNode(o);return s&&s.appendChild(p),p}if(!Array.isArray(o))return o&&o.appendChild&&s&&s.appendChild(o),o;if(typeof o[0]!="string"||!o[0]){for(var $=[],v=0;v=1.5:!0,g.isChromeOS&&(h.HI_DPI=!1),typeof document!="undefined"){var n=document.createElement("div");h.HI_DPI&&n.style.transform!==void 0&&(h.HAS_CSS_TRANSFORMS=!0),!g.isEdge&&typeof n.style.animationName!="undefined"&&(h.HAS_CSS_ANIMATION=!0),n=null}h.HAS_CSS_TRANSFORMS?h.translate=function(i,o,s){i.style.transform="translate("+Math.round(o)+"px, "+Math.round(s)+"px)"}:h.translate=function(i,o,s){i.style.top=Math.round(s)+"px",i.style.left=Math.round(o)+"px"}}),ace.define("ace/lib/net",["require","exports","module","ace/lib/dom"],function(e,h,m){/* +* based on code from: +* +* @license RequireJS text 0.25.0 Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved. +* Available via the MIT or new BSD license. +* see: http://github.com/jrburke/requirejs for details +*/var g=e("./dom");h.get=function(a,u){var r=new XMLHttpRequest;r.open("GET",a,!0),r.onreadystatechange=function(){r.readyState===4&&u(r.responseText)},r.send(null)},h.loadScript=function(a,u){var r=g.getDocumentHead(),f=document.createElement("script");f.src=a,r.appendChild(f),f.onload=f.onreadystatechange=function(l,n){(n||!f.readyState||f.readyState=="loaded"||f.readyState=="complete")&&(f=f.onload=f.onreadystatechange=null,n||u())}},h.qualifyURL=function(a){var u=document.createElement("a");return u.href=a,u.href}}),ace.define("ace/lib/oop",["require","exports","module"],function(e,h,m){h.inherits=function(g,a){g.super_=a,g.prototype=Object.create(a.prototype,{constructor:{value:g,enumerable:!1,writable:!0,configurable:!0}})},h.mixin=function(g,a){for(var u in a)g[u]=a[u];return g},h.implement=function(g,a){h.mixin(g,a)}}),ace.define("ace/lib/event_emitter",["require","exports","module"],function(e,h,m){var g={},a=function(){this.propagationStopped=!0},u=function(){this.defaultPrevented=!0};g._emit=g._dispatchEvent=function(r,f){this._eventRegistry||(this._eventRegistry={}),this._defaultHandlers||(this._defaultHandlers={});var l=this._eventRegistry[r]||[],n=this._defaultHandlers[r];if(!(!l.length&&!n)){(typeof f!="object"||!f)&&(f={}),f.type||(f.type=r),f.stopPropagation||(f.stopPropagation=a),f.preventDefault||(f.preventDefault=u),l=l.slice();for(var i=0;i1&&($=c[c.length-2]);var C=f[s+"Path"];return C==null?C=f.basePath:p=="/"&&(s=p=""),C&&C.slice(-1)!="/"&&(C+="/"),C+s+p+$+this.get("suffix")},h.setModuleUrl=function(o,s){return f.$moduleUrls[o]=s};var l=function(o,s){if(o==="ace/theme/textmate"||o==="./theme/textmate")return s(null,e("./theme/textmate"));if(n)return n(o,s);console.error("loader is not configured")},n;h.setLoader=function(o){n=o},h.dynamicModules=Object.create(null),h.$loading={},h.$loaded={},h.loadModule=function(o,s){var c;if(Array.isArray(o))var p=o[0],$=o[1];else if(typeof o=="string")var $=o;var v=function(C){if(C&&!h.$loading[$])return s&&s(C);if(h.$loading[$]||(h.$loading[$]=[]),h.$loading[$].push(s),!(h.$loading[$].length>1)){var y=function(){l($,function(_,b){b&&(h.$loaded[$]=b),h._emit("load.module",{name:$,module:b});var E=h.$loading[$];h.$loading[$]=null,E.forEach(function(x){x&&x(b)})})};if(!h.get("packaged"))return y();a.loadScript(h.moduleUrl($,p),y),i()}};if(h.dynamicModules[$])h.dynamicModules[$]().then(function(C){C.default?v(C.default):v(C)});else{try{c=this.$require($)}catch{}v(c||h.$loaded[$])}},h.$require=function(o){if(typeof m.require=="function"){var s="require";return m[s](o)}},h.setModuleLoader=function(o,s){h.dynamicModules[o]=s};var i=function(){!f.basePath&&!f.workerPath&&!f.modePath&&!f.themePath&&!Object.keys(f.$moduleUrls).length&&(console.error("Unable to infer path to ace from script src,","use ace.config.set('basePath', 'path') to enable dynamic loading of modes and themes","or with webpack use ace/webpack-resolver"),i=function(){})};h.version="1.32.6"}),ace.define("ace/loader_build",["require","exports","module","ace/lib/fixoldbrowsers","ace/config"],function(e,h,m){e("./lib/fixoldbrowsers");var g=e("./config");g.setLoader(function(f,l){e([f],function(n){l(null,n)})});var a=function(){return this||typeof window!="undefined"&&window}();m.exports=function(f){g.init=u,g.$require=e,f.require=e},u(!0);function u(f){if(!(!a||!a.document)){g.set("packaged",f||e.packaged||m.packaged||a.define&&(void 0).packaged);var l={},n="",i=document.currentScript||document._currentScript,o=i&&i.ownerDocument||document;i&&i.src&&(n=i.src.split(/[?#]/)[0].split("/").slice(0,-1).join("/")||"");for(var s=o.getElementsByTagName("script"),c=0;c ["+this.end.row+"/"+this.end.column+"]"},a.prototype.contains=function(u,r){return this.compare(u,r)==0},a.prototype.compareRange=function(u){var r,f=u.end,l=u.start;return r=this.compare(f.row,f.column),r==1?(r=this.compare(l.row,l.column),r==1?2:r==0?1:0):r==-1?-2:(r=this.compare(l.row,l.column),r==-1?-1:r==1?42:0)},a.prototype.comparePoint=function(u){return this.compare(u.row,u.column)},a.prototype.containsRange=function(u){return this.comparePoint(u.start)==0&&this.comparePoint(u.end)==0},a.prototype.intersects=function(u){var r=this.compareRange(u);return r==-1||r==0||r==1},a.prototype.isEnd=function(u,r){return this.end.row==u&&this.end.column==r},a.prototype.isStart=function(u,r){return this.start.row==u&&this.start.column==r},a.prototype.setStart=function(u,r){typeof u=="object"?(this.start.column=u.column,this.start.row=u.row):(this.start.row=u,this.start.column=r)},a.prototype.setEnd=function(u,r){typeof u=="object"?(this.end.column=u.column,this.end.row=u.row):(this.end.row=u,this.end.column=r)},a.prototype.inside=function(u,r){return this.compare(u,r)==0?!(this.isEnd(u,r)||this.isStart(u,r)):!1},a.prototype.insideStart=function(u,r){return this.compare(u,r)==0?!this.isEnd(u,r):!1},a.prototype.insideEnd=function(u,r){return this.compare(u,r)==0?!this.isStart(u,r):!1},a.prototype.compare=function(u,r){return!this.isMultiLine()&&u===this.start.row?rthis.end.column?1:0:uthis.end.row?1:this.start.row===u?r>=this.start.column?0:-1:this.end.row===u?r<=this.end.column?0:1:0},a.prototype.compareStart=function(u,r){return this.start.row==u&&this.start.column==r?-1:this.compare(u,r)},a.prototype.compareEnd=function(u,r){return this.end.row==u&&this.end.column==r?1:this.compare(u,r)},a.prototype.compareInside=function(u,r){return this.end.row==u&&this.end.column==r?1:this.start.row==u&&this.start.column==r?-1:this.compare(u,r)},a.prototype.clipRows=function(u,r){if(this.end.row>r)var f={row:r+1,column:0};else if(this.end.rowr)var l={row:r+1,column:0};else if(this.start.row1?(x++,x>4&&(x=1)):x=1,a.isIE){var L=Math.abs(w.clientX-O)>5||Math.abs(w.clientY-M)>5;(!k||L)&&(x=1),k&&clearTimeout(k),k=setTimeout(function(){k=null},y[x-1]||600),x==1&&(O=w.clientX,M=w.clientY)}if(w._clicks=x,_[b]("mousedown",w),x>4)x=0;else if(x>1)return _[b](T[x],w)}Array.isArray(C)||(C=[C]),C.forEach(function(w){o(w,"mousedown",S,E)})};function c(C){return 0|(C.ctrlKey?1:0)|(C.altKey?2:0)|(C.shiftKey?4:0)|(C.metaKey?8:0)}h.getModifierString=function(C){return g.KEY_MODS[c(C)]};function p(C,y,_){var b=c(y);if(!a.isMac&&u){if(y.getModifierState&&(y.getModifierState("OS")||y.getModifierState("Win"))&&(b|=8),u.altGr)if((3&b)!=3)u.altGr=0;else return;if(_===18||_===17){var E=y.location;if(_===17&&E===1)u[_]==1&&(r=y.timeStamp);else if(_===18&&b===3&&E===2){var x=y.timeStamp-r;x<50&&(u.altGr=!0)}}}if(_ in g.MODIFIER_KEYS&&(_=-1),!(!b&&_===13&&y.location===3&&(C(y,b,-_),y.defaultPrevented))){if(a.isChromeOS&&b&8){if(C(y,b,_),y.defaultPrevented)return;b&=~8}return!b&&!(_ in g.FUNCTION_KEYS)&&!(_ in g.PRINTABLE_KEYS)?!1:C(y,b,_)}}h.addCommandKeyListener=function(C,y,_){var b=null;o(C,"keydown",function(E){u[E.keyCode]=(u[E.keyCode]||0)+1;var x=p(y,E,E.keyCode);return b=E.defaultPrevented,x},_),o(C,"keypress",function(E){b&&(E.ctrlKey||E.altKey||E.shiftKey||E.metaKey)&&(h.stopEvent(E),b=null)},_),o(C,"keyup",function(E){u[E.keyCode]=null},_),u||($(),o(window,"focus",$))};function $(){u=Object.create(null)}if(typeof window=="object"&&window.postMessage&&!a.isOldIE){var v=1;h.nextTick=function(C,y){y=y||window;var _="zero-timeout-message-"+v++,b=function(E){E.data==_&&(h.stopPropagation(E),s(y,"message",b),C())};o(y,"message",b),y.postMessage(_,"*")}}h.$idleBlocked=!1,h.onIdle=function(C,y){return setTimeout(function _(){h.$idleBlocked?setTimeout(_,100):C()},y)},h.$idleBlockId=null,h.blockIdle=function(C){h.$idleBlockId&&clearTimeout(h.$idleBlockId),h.$idleBlocked=!0,h.$idleBlockId=setTimeout(function(){h.$idleBlocked=!1},C||100)},h.nextFrame=typeof window=="object"&&(window.requestAnimationFrame||window.mozRequestAnimationFrame||window.webkitRequestAnimationFrame||window.msRequestAnimationFrame||window.oRequestAnimationFrame),h.nextFrame?h.nextFrame=h.nextFrame.bind(window):h.nextFrame=function(C){setTimeout(C,17)}}),ace.define("ace/clipboard",["require","exports","module"],function(e,h,m){var g;m.exports={lineMode:!1,pasteCancelled:function(){return g&&g>Date.now()-50?!0:g=!1},cancel:function(){g=Date.now()}}}),ace.define("ace/keyboard/textinput",["require","exports","module","ace/lib/event","ace/config","ace/lib/useragent","ace/lib/dom","ace/lib/lang","ace/clipboard","ace/lib/keys"],function(e,h,m){var g=e("../lib/event"),a=e("../config").nls,u=e("../lib/useragent"),r=e("../lib/dom"),f=e("../lib/lang"),l=e("../clipboard"),n=u.isChrome<18,i=u.isIE,o=u.isChrome>63,s=400,c=e("../lib/keys"),p=c.KEY_MODS,$=u.isIOS,v=$?/\s/:/\n/,C=u.isMobile,y;y=function(_,b){var E=r.createElement("textarea");E.className="ace_text-input",E.setAttribute("wrap","off"),E.setAttribute("autocorrect","off"),E.setAttribute("autocapitalize","off"),E.setAttribute("spellcheck","false"),E.style.opacity="0",_.insertBefore(E,_.firstChild);var x=!1,O=!1,M=!1,k=!1,T="";C||(E.style.fontSize="1px");var S=!1,w=!1,L="",q=0,A=0,I=0,F=Number.MAX_SAFE_INTEGER,V=Number.MIN_SAFE_INTEGER,R=0;try{var B=document.activeElement===E}catch{}this.setNumberOfExtraLines=function(X){if(F=Number.MAX_SAFE_INTEGER,V=Number.MIN_SAFE_INTEGER,X<0){R=0;return}R=X},this.setAriaOptions=function(X){if(X.activeDescendant?(E.setAttribute("aria-haspopup","true"),E.setAttribute("aria-autocomplete",X.inline?"both":"list"),E.setAttribute("aria-activedescendant",X.activeDescendant)):(E.setAttribute("aria-haspopup","false"),E.setAttribute("aria-autocomplete","both"),E.removeAttribute("aria-activedescendant")),X.role&&E.setAttribute("role",X.role),X.setLabel&&(E.setAttribute("aria-roledescription",a("editor")),b.session)){var ae=b.session.selection.cursor.row;E.setAttribute("aria-label",a("Cursor at row $0",[ae+1]))}},this.setAriaOptions({role:"textbox"}),g.addListener(E,"blur",function(X){w||(b.onBlur(X),B=!1)},b),g.addListener(E,"focus",function(X){if(!w){if(B=!0,u.isEdge)try{if(!document.hasFocus())return}catch{}b.onFocus(X),u.isEdge?setTimeout(P):P()}},b),this.$focusScroll=!1,this.focus=function(){if(this.setAriaOptions({setLabel:b.renderer.enableKeyboardAccessibility}),T||o||this.$focusScroll=="browser")return E.focus({preventScroll:!0});var X=E.style.top;E.style.position="fixed",E.style.top="0px";try{var ae=E.getBoundingClientRect().top!=0}catch{return}var oe=[];if(ae)for(var G=E.parentElement;G&&G.nodeType==1;)oe.push(G),G.setAttribute("ace_nocontext","true"),!G.parentElement&&G.getRootNode?G=G.getRootNode().host:G=G.parentElement;E.focus({preventScroll:!0}),ae&&oe.forEach(function(U){U.removeAttribute("ace_nocontext")}),setTimeout(function(){E.style.position="",E.style.top=="0px"&&(E.style.top=X)},0)},this.blur=function(){E.blur()},this.isFocused=function(){return B},b.on("beforeEndOperation",function(){var X=b.curOp,ae=X&&X.command&&X.command.name;if(ae!="insertstring"){var oe=ae&&(X.docChanged||X.selectionChanged);M&&oe&&(L=E.value="",J()),P()}});var N=function(X,ae){for(var oe=ae,G=1;G<=X-F&&G<2*R+1;G++)oe+=b.session.getLine(X-G).length+1;return oe},P=$?function(X){if(!(!B||x&&!X||k)){X||(X="");var ae=` + ab`+X+`cde fg +`;ae!=E.value&&(E.value=L=ae);var oe=4,G=4+(X.length||(b.selection.isEmpty()?0:1));(q!=oe||A!=G)&&E.setSelectionRange(oe,G),q=oe,A=G}}:function(){if(!(M||k)&&!(!B&&!H)){M=!0;var X=0,ae=0,oe="";if(b.session){var G=b.selection,U=G.getRange(),Y=G.cursor.row;Y===V+1?(F=V+1,V=F+2*R):Y===F-1?(V=F-1,F=V-2*R):(YV+1)&&(F=Y>R?Y-R:0,V=Y>R?Y+R:2*R);for(var ee=[],re=F;re<=V;re++)ee.push(b.session.getLine(re));if(oe=ee.join(` +`),X=N(U.start.row,U.start.column),ae=N(U.end.row,U.end.column),U.start.rowV){var ce=b.session.getLine(V+1);ae=U.end.row>V+1?ce.length:U.end.column,ae+=oe.length+1,oe=oe+` +`+ce}else C&&Y>0&&(oe=` +`+oe,ae+=1,X+=1);oe.length>s&&(X=L.length&&X.value===L&&L&&X.selectionEnd!==A},D=function(X){M||(x?x=!1:j(E)?(b.selectAll(),P()):C&&E.selectionStart!=q&&P())},W=null;this.setInputHandler=function(X){W=X},this.getInputHandler=function(){return W};var H=!1,z=function(X,ae){if(H&&(H=!1),O)return P(),X&&b.onPaste(X),O=!1,"";for(var oe=E.selectionStart,G=E.selectionEnd,U=q,Y=L.length-A,ee=X,re=X.length-oe,de=X.length-G,ce=0;U>0&&L[ce]==X[ce];)ce++,U--;for(ee=ee.slice(ce),ce=1;Y>0&&L.length-ce>q-1&&L[L.length-ce]==X[X.length-ce];)ce++,Y--;re-=ce-1,de-=ce-1;var ve=ee.length-ce+1;if(ve<0&&(U=-ve,ve=0),ee=ee.slice(0,ve),!ae&&!ee&&!re&&!U&&!Y&&!de)return"";k=!0;var xe=!1;return u.isAndroid&&ee==". "&&(ee=" ",xe=!0),ee&&!U&&!Y&&!re&&!de||S?b.onTextInput(ee):b.onTextInput(ee,{extendLeft:U,extendRight:Y,restoreStart:re,restoreEnd:de}),k=!1,L=X,q=oe,A=G,I=de,xe?` +`:ee},K=function(X){if(M)return _e();if(X&&X.inputType){if(X.inputType=="historyUndo")return b.execCommand("undo");if(X.inputType=="historyRedo")return b.execCommand("redo")}var ae=E.value,oe=z(ae,!0);(ae.length>s+100||v.test(oe)||C&&q<1&&q==A)&&P()},Z=function(X,ae,oe){var G=X.clipboardData||window.clipboardData;if(!(!G||n)){var U=i||oe?"Text":"text/plain";try{return ae?G.setData(U,ae)!==!1:G.getData(U)}catch(Y){if(!oe)return Z(Y,ae,!0)}}},ie=function(X,ae){var oe=b.getCopyText();if(!oe)return g.preventDefault(X);Z(X,oe)?($&&(P(oe),x=oe,setTimeout(function(){x=!1},10)),ae?b.onCut():b.onCopy(),g.preventDefault(X)):(x=!0,E.value=oe,E.select(),setTimeout(function(){x=!1,P(),ae?b.onCut():b.onCopy()}))},se=function(X){ie(X,!0)},ue=function(X){ie(X,!1)},fe=function(X){var ae=Z(X);l.pasteCancelled()||(typeof ae=="string"?(ae&&b.onPaste(ae,X),u.isIE&&setTimeout(P),g.preventDefault(X)):(E.value="",O=!0))};g.addCommandKeyListener(E,function(X,ae,oe){if(!M)return b.onCommandKey(X,ae,oe)},b),g.addListener(E,"select",D,b),g.addListener(E,"input",K,b),g.addListener(E,"cut",se,b),g.addListener(E,"copy",ue,b),g.addListener(E,"paste",fe,b),(!("oncut"in E)||!("oncopy"in E)||!("onpaste"in E))&&g.addListener(_,"keydown",function(X){if(!(u.isMac&&!X.metaKey||!X.ctrlKey))switch(X.keyCode){case 67:ue(X);break;case 86:fe(X);break;case 88:se(X);break}},b);var ye=function(X){if(!(M||!b.onCompositionStart||b.$readOnly)&&(M={},!S)){X.data&&(M.useTextareaForIME=!1),setTimeout(_e,0),b._signal("compositionStart"),b.on("mousedown",Q);var ae=b.getSelectionRange();ae.end.row=ae.start.row,ae.end.column=ae.start.column,M.markerRange=ae,M.selectionStart=q,b.onCompositionStart(M),M.useTextareaForIME?(L=E.value="",q=0,A=0):(E.msGetInputContext&&(M.context=E.msGetInputContext()),E.getInputContext&&(M.context=E.getInputContext()))}},_e=function(){if(!(!M||!b.onCompositionUpdate||b.$readOnly)){if(S)return Q();if(M.useTextareaForIME)b.onCompositionUpdate(E.value);else{var X=E.value;z(X),M.markerRange&&(M.context&&(M.markerRange.start.column=M.selectionStart=M.context.compositionStartOffset),M.markerRange.end.column=M.markerRange.start.column+A-M.selectionStart+I)}}},J=function(X){!b.onCompositionEnd||b.$readOnly||(M=!1,b.onCompositionEnd(),b.off("mousedown",Q),X&&K())};function Q(){w=!0,E.blur(),E.focus(),w=!1}var ne=f.delayedCall(_e,50).schedule.bind(null,null);function le(X){X.keyCode==27&&E.value.lengthA&&L[de]==` +`?ce=c.end:reA&&L.slice(0,de).split(` +`).length>2?ce=c.down:de>A&&L[de-1]==" "?(ce=c.right,ve=p.option):(de>A||de==A&&A!=q&&re==de)&&(ce=c.right),re!==de&&(ve|=p.shift),ce){var xe=ae.onCommandKey({},ve,ce);if(!xe&&ae.commands){ce=c.keyCodeToString(ce);var ge=ae.commands.findKeyCommand(ve,ce);ge&&ae.execCommand(ge)}q=re,A=de,P("")}}};document.addEventListener("selectionchange",Y),ae.on("destroy",function(){document.removeEventListener("selectionchange",Y)})}this.destroy=function(){E.parentElement&&E.parentElement.removeChild(E)}},h.TextInput=y,h.$setUserAgentForTests=function(_,b){C=_,$=b}}),ace.define("ace/mouse/default_handlers",["require","exports","module","ace/lib/useragent"],function(e,h,m){var g=e("../lib/useragent"),a=0,u=550,r=function(){function n(i){i.$clickSelection=null;var o=i.editor;o.setDefaultHandler("mousedown",this.onMouseDown.bind(i)),o.setDefaultHandler("dblclick",this.onDoubleClick.bind(i)),o.setDefaultHandler("tripleclick",this.onTripleClick.bind(i)),o.setDefaultHandler("quadclick",this.onQuadClick.bind(i)),o.setDefaultHandler("mousewheel",this.onMouseWheel.bind(i));var s=["select","startSelect","selectEnd","selectAllEnd","selectByWordsEnd","selectByLinesEnd","dragWait","dragWaitEnd","focusWait"];s.forEach(function(c){i[c]=this[c]},this),i.selectByLines=this.extendSelectionBy.bind(i,"getLineRange"),i.selectByWords=this.extendSelectionBy.bind(i,"getWordRange")}return n.prototype.onMouseDown=function(i){var o=i.inSelection(),s=i.getDocumentPosition();this.mousedownEvent=i;var c=this.editor,p=i.getButton();if(p!==0){var $=c.getSelectionRange(),v=$.isEmpty();(v||p==1)&&c.selection.moveToPosition(s),p==2&&(c.textInput.onContextMenu(i.domEvent),g.isMozilla||i.preventDefault());return}if(this.mousedownEvent.time=Date.now(),o&&!c.isFocused()&&(c.focus(),this.$focusTimeout&&!this.$clickSelection&&!c.inMultiSelectMode)){this.setState("focusWait"),this.captureMouse(i);return}return this.captureMouse(i),this.startSelect(s,i.domEvent._clicks>1),i.preventDefault()},n.prototype.startSelect=function(i,o){i=i||this.editor.renderer.screenToTextCoordinates(this.x,this.y);var s=this.editor;!this.mousedownEvent||(this.mousedownEvent.getShiftKey()?s.selection.selectToPosition(i):o||s.selection.moveToPosition(i),o||this.select(),s.setStyle("ace_selecting"),this.setState("select"))},n.prototype.select=function(){var i,o=this.editor,s=o.renderer.screenToTextCoordinates(this.x,this.y);if(this.$clickSelection){var c=this.$clickSelection.comparePoint(s);if(c==-1)i=this.$clickSelection.end;else if(c==1)i=this.$clickSelection.start;else{var p=l(this.$clickSelection,s);s=p.cursor,i=p.anchor}o.selection.setSelectionAnchor(i.row,i.column)}o.selection.selectToPosition(s),o.renderer.scrollCursorIntoView()},n.prototype.extendSelectionBy=function(i){var o,s=this.editor,c=s.renderer.screenToTextCoordinates(this.x,this.y),p=s.selection[i](c.row,c.column);if(this.$clickSelection){var $=this.$clickSelection.comparePoint(p.start),v=this.$clickSelection.comparePoint(p.end);if($==-1&&v<=0)o=this.$clickSelection.end,(p.end.row!=c.row||p.end.column!=c.column)&&(c=p.start);else if(v==1&&$>=0)o=this.$clickSelection.start,(p.start.row!=c.row||p.start.column!=c.column)&&(c=p.end);else if($==-1&&v==1)c=p.end,o=p.start;else{var C=l(this.$clickSelection,c);c=C.cursor,o=C.anchor}s.selection.setSelectionAnchor(o.row,o.column)}s.selection.selectToPosition(c),s.renderer.scrollCursorIntoView()},n.prototype.selectByLinesEnd=function(){this.$clickSelection=null,this.editor.unsetStyle("ace_selecting")},n.prototype.focusWait=function(){var i=f(this.mousedownEvent.x,this.mousedownEvent.y,this.x,this.y),o=Date.now();(i>a||o-this.mousedownEvent.time>this.$focusTimeout)&&this.startSelect(this.mousedownEvent.getDocumentPosition())},n.prototype.onDoubleClick=function(i){var o=i.getDocumentPosition(),s=this.editor,c=s.session,p=c.getBracketRange(o);p?(p.isEmpty()&&(p.start.column--,p.end.column++),this.setState("select")):(p=s.selection.getWordRange(o.row,o.column),this.setState("selectByWords")),this.$clickSelection=p,this.select()},n.prototype.onTripleClick=function(i){var o=i.getDocumentPosition(),s=this.editor;this.setState("selectByLines");var c=s.getSelectionRange();c.isMultiLine()&&c.contains(o.row,o.column)?(this.$clickSelection=s.selection.getLineRange(c.start.row),this.$clickSelection.end=s.selection.getLineRange(c.end.row).end):this.$clickSelection=s.selection.getLineRange(o.row),this.select()},n.prototype.onQuadClick=function(i){var o=this.editor;o.selectAll(),this.$clickSelection=o.getSelectionRange(),this.setState("selectAll")},n.prototype.onMouseWheel=function(i){if(!i.getAccelKey()){i.getShiftKey()&&i.wheelY&&!i.wheelX&&(i.wheelX=i.wheelY,i.wheelY=0);var o=this.editor;this.$lastScroll||(this.$lastScroll={t:0,vx:0,vy:0,allowed:0});var s=this.$lastScroll,c=i.domEvent.timeStamp,p=c-s.t,$=p?i.wheelX/p:s.vx,v=p?i.wheelY/p:s.vy;p=1&&o.renderer.isScrollableBy(i.wheelX*i.speed,0)&&(y=!0),C<=1&&o.renderer.isScrollableBy(0,i.wheelY*i.speed)&&(y=!0),y)s.allowed=c;else if(c-s.allowedu.clientHeight;r||a.preventDefault()}}),ace.define("ace/tooltip",["require","exports","module","ace/lib/dom","ace/lib/event","ace/range","ace/lib/scroll"],function(e,h,m){var g=this&&this.__extends||function(){var c=function(p,$){return c=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(v,C){v.__proto__=C}||function(v,C){for(var y in C)Object.prototype.hasOwnProperty.call(C,y)&&(v[y]=C[y])},c(p,$)};return function(p,$){if(typeof $!="function"&&$!==null)throw new TypeError("Class extends value "+String($)+" is not a constructor or null");c(p,$);function v(){this.constructor=p}p.prototype=$===null?Object.create($):(v.prototype=$.prototype,new v)}}(),a=this&&this.__values||function(c){var p=typeof Symbol=="function"&&Symbol.iterator,$=p&&c[p],v=0;if($)return $.call(c);if(c&&typeof c.length=="number")return{next:function(){return c&&v>=c.length&&(c=void 0),{value:c&&c[v++],done:!c}}};throw new TypeError(p?"Object is not iterable.":"Symbol.iterator is not defined.")},u=e("./lib/dom");e("./lib/event");var r=e("./range").Range,f=e("./lib/scroll").preventParentScroll,l="ace_tooltip",n=function(){function c(p){this.isOpen=!1,this.$element=null,this.$parentNode=p}return c.prototype.$init=function(){return this.$element=u.createElement("div"),this.$element.className=l,this.$element.style.display="none",this.$parentNode.appendChild(this.$element),this.$element},c.prototype.getElement=function(){return this.$element||this.$init()},c.prototype.setText=function(p){this.getElement().textContent=p},c.prototype.setHtml=function(p){this.getElement().innerHTML=p},c.prototype.setPosition=function(p,$){this.getElement().style.left=p+"px",this.getElement().style.top=$+"px"},c.prototype.setClassName=function(p){u.addCssClass(this.getElement(),p)},c.prototype.setTheme=function(p){this.$element.className=l+" "+(p.isDark?"ace_dark ":"")+(p.cssClass||"")},c.prototype.show=function(p,$,v){p!=null&&this.setText(p),$!=null&&v!=null&&this.setPosition($,v),this.isOpen||(this.getElement().style.display="block",this.isOpen=!0)},c.prototype.hide=function(p){this.isOpen&&(this.getElement().style.display="none",this.getElement().className=l,this.isOpen=!1)},c.prototype.getHeight=function(){return this.getElement().offsetHeight},c.prototype.getWidth=function(){return this.getElement().offsetWidth},c.prototype.destroy=function(){this.isOpen=!1,this.$element&&this.$element.parentNode&&this.$element.parentNode.removeChild(this.$element)},c}(),i=function(){function c(){this.popups=[]}return c.prototype.addPopup=function(p){this.popups.push(p),this.updatePopups()},c.prototype.removePopup=function(p){var $=this.popups.indexOf(p);$!==-1&&(this.popups.splice($,1),this.updatePopups())},c.prototype.updatePopups=function(){var p,$,v,C;this.popups.sort(function(T,S){return S.priority-T.priority});var y=[];try{for(var _=a(this.popups),b=_.next();!b.done;b=_.next()){var E=b.value,x=!0;try{for(var O=(v=void 0,a(y)),M=O.next();!M.done;M=O.next()){var k=M.value;if(this.doPopupsOverlap(k,E)){x=!1;break}}}catch(T){v={error:T}}finally{try{M&&!M.done&&(C=O.return)&&C.call(O)}finally{if(v)throw v.error}}x?y.push(E):E.hide()}}catch(T){p={error:T}}finally{try{b&&!b.done&&($=_.return)&&$.call(_)}finally{if(p)throw p.error}}},c.prototype.doPopupsOverlap=function(p,$){var v=p.getElement().getBoundingClientRect(),C=$.getElement().getBoundingClientRect();return v.leftC.left&&v.topC.top},c}(),o=new i;h.popupManager=o,h.Tooltip=n;var s=function(c){g(p,c);function p($){$===void 0&&($=document.body);var v=c.call(this,$)||this;v.timeout=void 0,v.lastT=0,v.idleTime=350,v.lastEvent=void 0,v.onMouseOut=v.onMouseOut.bind(v),v.onMouseMove=v.onMouseMove.bind(v),v.waitForHover=v.waitForHover.bind(v),v.hide=v.hide.bind(v);var C=v.getElement();return C.style.whiteSpace="pre-wrap",C.style.pointerEvents="auto",C.addEventListener("mouseout",v.onMouseOut),C.tabIndex=-1,C.addEventListener("blur",function(){C.contains(document.activeElement)||this.hide()}.bind(v)),C.addEventListener("wheel",f),v}return p.prototype.addToEditor=function($){$.on("mousemove",this.onMouseMove),$.on("mousedown",this.hide),$.renderer.getMouseEventTarget().addEventListener("mouseout",this.onMouseOut,!0)},p.prototype.removeFromEditor=function($){$.off("mousemove",this.onMouseMove),$.off("mousedown",this.hide),$.renderer.getMouseEventTarget().removeEventListener("mouseout",this.onMouseOut,!0),this.timeout&&(clearTimeout(this.timeout),this.timeout=null)},p.prototype.onMouseMove=function($,v){this.lastEvent=$,this.lastT=Date.now();var C=v.$mouseHandler.isMousePressed;if(this.isOpen){var y=this.lastEvent&&this.lastEvent.getDocumentPosition();(!this.range||!this.range.contains(y.row,y.column)||C||this.isOutsideOfText(this.lastEvent))&&this.hide()}this.timeout||C||(this.lastEvent=$,this.timeout=setTimeout(this.waitForHover,this.idleTime))},p.prototype.waitForHover=function(){this.timeout&&clearTimeout(this.timeout);var $=Date.now()-this.lastT;if(this.idleTime-$>10){this.timeout=setTimeout(this.waitForHover,this.idleTime-$);return}this.timeout=null,this.lastEvent&&!this.isOutsideOfText(this.lastEvent)&&this.$gatherData(this.lastEvent,this.lastEvent.editor)},p.prototype.isOutsideOfText=function($){var v=$.editor,C=$.getDocumentPosition(),y=v.session.getLine(C.row);if(C.column==y.length){var _=v.renderer.pixelToScreenCoordinates($.clientX,$.clientY),b=v.session.documentToScreenPosition(C.row,C.column);if(b.column!=_.column||b.row!=_.row)return!0}return!1},p.prototype.setDataProvider=function($){this.$gatherData=$},p.prototype.showForRange=function($,v,C,y){var _=10;if(!(y&&y!=this.lastEvent)&&!(this.isOpen&&document.activeElement==this.getElement())){var b=$.renderer;this.isOpen||(o.addPopup(this),this.$registerCloseEvents(),this.setTheme(b.theme)),this.isOpen=!0,this.addMarker(v,$.session),this.range=r.fromPoints(v.start,v.end);var E=b.textToScreenCoordinates(v.start.row,v.start.column),x=b.scroller.getBoundingClientRect();E.pageX=o.length&&(o=void 0),{value:o&&o[p++],done:!o}}};throw new TypeError(s?"Object is not iterable.":"Symbol.iterator is not defined.")},u=e("../lib/dom"),r=e("../lib/event"),f=e("../tooltip").Tooltip,l=e("../config").nls;function n(o){var s=o.editor,c=s.renderer.$gutterLayer,p=new i(s);o.editor.setDefaultHandler("guttermousedown",function(b){if(!(!s.isFocused()||b.getButton()!=0)){var E=c.getRegion(b);if(E!="foldWidgets"){var x=b.getDocumentPosition().row,O=s.session.selection;if(b.getShiftKey())O.selectTo(x,0);else{if(b.domEvent.detail==2)return s.selectAll(),b.preventDefault();o.$clickSelection=s.selection.getLineRange(x)}return o.setState("selectByLines"),o.captureMouse(b),b.preventDefault()}}});var $,v;function C(){var b=v.getDocumentPosition().row,E=s.session.getLength();if(b==E){var x=s.renderer.pixelToScreenCoordinates(0,v.y).row,O=v.$pos;if(x>s.session.documentToScreenRow(O.row,O.column))return y()}if(p.showTooltip(b),!!p.isOpen)if(s.on("mousewheel",y),o.$tooltipFollowsMouse)_(v);else{var M=v.getGutterRow(),k=c.$lines.get(M);if(k){var T=k.element.querySelector(".ace_gutter_annotation"),S=T.getBoundingClientRect(),w=p.getElement().style;w.left=S.right+"px",w.top=S.bottom+"px"}else _(v)}}function y(){$&&($=clearTimeout($)),p.isOpen&&(p.hideTooltip(),s.off("mousewheel",y))}function _(b){p.setPosition(b.x,b.y)}o.editor.setDefaultHandler("guttermousemove",function(b){var E=b.domEvent.target||b.domEvent.srcElement;if(u.hasCssClass(E,"ace_fold-widget"))return y();p.isOpen&&o.$tooltipFollowsMouse&&_(b),v=b,!$&&($=setTimeout(function(){$=null,v&&!o.isMousePressed?C():y()},50))}),r.addListener(s.renderer.$gutter,"mouseout",function(b){v=null,!(!p.isOpen||$)&&($=setTimeout(function(){$=null,y()},50))},s),s.on("changeSession",y),s.on("input",y)}h.GutterHandler=n;var i=function(o){g(s,o);function s(c){var p=o.call(this,c.container)||this;return p.editor=c,p}return s.prototype.setPosition=function(c,p){var $=window.innerWidth||document.documentElement.clientWidth,v=window.innerHeight||document.documentElement.clientHeight,C=this.getWidth(),y=this.getHeight();c+=15,p+=15,c+C>$&&(c-=c+C-$),p+y>v&&(p-=20+y),f.prototype.setPosition.call(this,c,p)},Object.defineProperty(s,"annotationLabels",{get:function(){return{error:{singular:l("error"),plural:l("errors")},warning:{singular:l("warning"),plural:l("warnings")},info:{singular:l("information message"),plural:l("information messages")}}},enumerable:!1,configurable:!0}),s.prototype.showTooltip=function(c){var p=this.editor.renderer.$gutterLayer,$=p.$annotations[c],v;$?v={text:Array.from($.text),type:Array.from($.type)}:v={text:[],type:[]};var C=p.session.getFoldLine(c);if(C&&p.$showFoldedAnnotations){for(var y={error:[],warning:[],info:[]},_,b=c+1;b<=C.end.row;b++)if(!!p.$annotations[b])for(var E=0;E ").concat(v.text[b]);M[v.type[b].replace("_fold","")].push(T)}var S=[].concat(M.error,M.warning,M.info).join("
");this.setHtml(S),this.$element.setAttribute("aria-live","polite"),this.isOpen||(this.setTheme(this.editor.renderer.theme),this.setClassName("ace_gutter-tooltip")),this.show(),this.editor._signal("showGutterTooltip",this)},s.prototype.hideTooltip=function(){this.$element.removeAttribute("aria-live"),this.hide(),this.editor._signal("hideGutterTooltip",this)},s.annotationsToSummaryString=function(c){var p,$,v=[],C=["error","warning","info"];try{for(var y=a(C),_=y.next();!_.done;_=y.next()){var b=_.value;if(!!c[b].length){var E=c[b].length===1?s.annotationLabels[b].singular:s.annotationLabels[b].plural;v.push("".concat(c[b].length," ").concat(E))}}}catch(x){p={error:x}}finally{try{_&&!_.done&&($=y.return)&&$.call(y)}finally{if(p)throw p.error}}return v.join(", ")},s}(f);h.GutterTooltip=i}),ace.define("ace/mouse/mouse_event",["require","exports","module","ace/lib/event","ace/lib/useragent"],function(e,h,m){var g=e("../lib/event"),a=e("../lib/useragent"),u=function(){function r(f,l){this.speed,this.wheelX,this.wheelY,this.domEvent=f,this.editor=l,this.x=this.clientX=f.clientX,this.y=this.clientY=f.clientY,this.$pos=null,this.$inSelection=null,this.propagationStopped=!1,this.defaultPrevented=!1}return r.prototype.stopPropagation=function(){g.stopPropagation(this.domEvent),this.propagationStopped=!0},r.prototype.preventDefault=function(){g.preventDefault(this.domEvent),this.defaultPrevented=!0},r.prototype.stop=function(){this.stopPropagation(),this.preventDefault()},r.prototype.getDocumentPosition=function(){return this.$pos?this.$pos:(this.$pos=this.editor.renderer.screenToTextCoordinates(this.clientX,this.clientY),this.$pos)},r.prototype.getGutterRow=function(){var f=this.getDocumentPosition().row,l=this.editor.session.documentToScreenRow(f,0),n=this.editor.session.documentToScreenRow(this.editor.renderer.$gutterLayer.$lines.get(0).row,0);return l-n},r.prototype.inSelection=function(){if(this.$inSelection!==null)return this.$inSelection;var f=this.editor,l=f.getSelectionRange();if(l.isEmpty())this.$inSelection=!1;else{var n=this.getDocumentPosition();this.$inSelection=l.contains(n.row,n.column)}return this.$inSelection},r.prototype.getButton=function(){return g.getButton(this.domEvent)},r.prototype.getShiftKey=function(){return this.domEvent.shiftKey},r.prototype.getAccelKey=function(){return a.isMac?this.domEvent.metaKey:this.domEvent.ctrlKey},r}();h.MouseEvent=u}),ace.define("ace/mouse/dragdrop_handler",["require","exports","module","ace/lib/dom","ace/lib/event","ace/lib/useragent"],function(e,h,m){var g=e("../lib/dom"),a=e("../lib/event"),u=e("../lib/useragent"),r=200,f=200,l=5;function n(o){var s=o.editor,c=g.createElement("div");c.style.cssText="top:-100px;position:absolute;z-index:2147483647;opacity:0.5",c.textContent="\xA0";var p=["dragWait","dragWaitEnd","startDrag","dragReadyEnd","onMouseDrag"];p.forEach(function(N){o[N]=this[N]},this),s.on("mousedown",this.onMouseDown.bind(o));var $=s.container,v,C,y,_,b,E,x=0,O,M,k,T,S;this.onDragStart=function(N){if(this.cancelDrag||!$.draggable){var P=this;return setTimeout(function(){P.startSelect(),P.captureMouse(N)},0),N.preventDefault()}b=s.getSelectionRange();var j=N.dataTransfer;j.effectAllowed=s.getReadOnly()?"copy":"copyMove",s.container.appendChild(c),j.setDragImage&&j.setDragImage(c,0,0),setTimeout(function(){s.container.removeChild(c)}),j.clearData(),j.setData("Text",s.session.getTextRange()),M=!0,this.setState("drag")},this.onDragEnd=function(N){if($.draggable=!1,M=!1,this.setState(null),!s.getReadOnly()){var P=N.dataTransfer.dropEffect;!O&&P=="move"&&s.session.remove(s.getSelectionRange()),s.$resetCursorStyle()}this.editor.unsetStyle("ace_dragging"),this.editor.renderer.setCursorStyle("")},this.onDragEnter=function(N){if(!(s.getReadOnly()||!R(N.dataTransfer)))return C=N.clientX,y=N.clientY,v||A(),x++,N.dataTransfer.dropEffect=O=B(N),a.preventDefault(N)},this.onDragOver=function(N){if(!(s.getReadOnly()||!R(N.dataTransfer)))return C=N.clientX,y=N.clientY,v||(A(),x++),F!==null&&(F=null),N.dataTransfer.dropEffect=O=B(N),a.preventDefault(N)},this.onDragLeave=function(N){if(x--,x<=0&&v)return I(),O=null,a.preventDefault(N)},this.onDrop=function(N){if(!!E){var P=N.dataTransfer;if(M)switch(O){case"move":b.contains(E.row,E.column)?b={start:E,end:E}:b=s.moveText(b,E);break;case"copy":b=s.moveText(b,E,!0);break}else{var j=P.getData("Text");b={start:E,end:s.session.insert(E,j)},s.focus(),O=null}return I(),a.preventDefault(N)}},a.addListener($,"dragstart",this.onDragStart.bind(o),s),a.addListener($,"dragend",this.onDragEnd.bind(o),s),a.addListener($,"dragenter",this.onDragEnter.bind(o),s),a.addListener($,"dragover",this.onDragOver.bind(o),s),a.addListener($,"dragleave",this.onDragLeave.bind(o),s),a.addListener($,"drop",this.onDrop.bind(o),s);function w(N,P){var j=Date.now(),D=!P||N.row!=P.row,W=!P||N.column!=P.column;if(!T||D||W)s.moveCursorToPosition(N),T=j,S={x:C,y};else{var H=i(S.x,S.y,C,y);H>l?T=null:j-T>=f&&(s.renderer.scrollCursorIntoView(),T=null)}}function L(N,P){var j=Date.now(),D=s.renderer.layerConfig.lineHeight,W=s.renderer.layerConfig.characterWidth,H=s.renderer.scroller.getBoundingClientRect(),z={x:{left:C-H.left,right:H.right-C},y:{top:y-H.top,bottom:H.bottom-y}},K=Math.min(z.x.left,z.x.right),Z=Math.min(z.y.top,z.y.bottom),ie={row:N.row,column:N.column};K/W<=2&&(ie.column+=z.x.left=r&&s.renderer.scrollCursorIntoView(ie):k=j:k=null}function q(){var N=E;E=s.renderer.screenToTextCoordinates(C,y),w(E,N),L(E,N)}function A(){b=s.selection.toOrientedRange(),v=s.session.addMarker(b,"ace_selection",s.getSelectionStyle()),s.clearSelection(),s.isFocused()&&s.renderer.$cursorLayer.setBlinking(!1),clearInterval(_),q(),_=setInterval(q,20),x=0,a.addListener(document,"mousemove",V)}function I(){clearInterval(_),s.session.removeMarker(v),v=null,s.selection.fromOrientedRange(b),s.isFocused()&&!M&&s.$resetCursorStyle(),b=null,E=null,x=0,k=null,T=null,a.removeListener(document,"mousemove",V)}var F=null;function V(){F==null&&(F=setTimeout(function(){F!=null&&v&&I()},20))}function R(N){var P=N.types;return!P||Array.prototype.some.call(P,function(j){return j=="text/plain"||j=="Text"})}function B(N){var P=["copy","copymove","all","uninitialized"],j=["move","copymove","linkmove","all","uninitialized"],D=u.isMac?N.altKey:N.ctrlKey,W="uninitialized";try{W=N.dataTransfer.effectAllowed.toLowerCase()}catch{}var H="none";return D&&P.indexOf(W)>=0?H="copy":j.indexOf(W)>=0?H="move":P.indexOf(W)>=0&&(H="copy"),H}}(function(){this.dragWait=function(){var o=Date.now()-this.mousedownEvent.time;o>this.editor.getDragDelay()&&this.startDrag()},this.dragWaitEnd=function(){var o=this.editor.container;o.draggable=!1,this.startSelect(this.mousedownEvent.getDocumentPosition()),this.selectEnd()},this.dragReadyEnd=function(o){this.editor.$resetCursorStyle(),this.editor.unsetStyle("ace_dragging"),this.editor.renderer.setCursorStyle(""),this.dragWaitEnd()},this.startDrag=function(){this.cancelDrag=!1;var o=this.editor,s=o.container;s.draggable=!0,o.renderer.$cursorLayer.setBlinking(!1),o.setStyle("ace_dragging");var c=u.isWin?"default":"move";o.renderer.setCursorStyle(c),this.setState("dragReady")},this.onMouseDrag=function(o){var s=this.editor.container;if(u.isIE&&this.state=="dragReady"){var c=i(this.mousedownEvent.x,this.mousedownEvent.y,this.x,this.y);c>3&&s.dragDrop()}if(this.state==="dragWait"){var c=i(this.mousedownEvent.x,this.mousedownEvent.y,this.x,this.y);c>0&&(s.draggable=!1,this.startSelect(this.mousedownEvent.getDocumentPosition()))}},this.onMouseDown=function(o){if(!!this.$dragEnabled){this.mousedownEvent=o;var s=this.editor,c=o.inSelection(),p=o.getButton(),$=o.domEvent.detail||1;if($===1&&p===0&&c){if(o.editor.inMultiSelectMode&&(o.getAccelKey()||o.getShiftKey()))return;this.mousedownEvent.time=Date.now();var v=o.domEvent.target||o.domEvent.srcElement;if("unselectable"in v&&(v.unselectable="on"),s.getDragDelay()){if(u.isWebKit){this.cancelDrag=!0;var C=s.container;C.draggable=!0}this.setState("dragWait")}else this.startDrag();this.captureMouse(o,this.onMouseDrag.bind(this)),o.defaultPrevented=!0}}}}).call(n.prototype);function i(o,s,c,p){return Math.sqrt(Math.pow(c-o,2)+Math.pow(p-s,2))}h.DragdropHandler=n}),ace.define("ace/mouse/touch_handler",["require","exports","module","ace/mouse/mouse_event","ace/lib/event","ace/lib/dom"],function(e,h,m){var g=e("./mouse_event").MouseEvent,a=e("../lib/event"),u=e("../lib/dom");h.addTouchListeners=function(r,f){var l="scroll",n,i,o,s,c,p,$=0,v,C=0,y=0,_=0,b,E;function x(){var w=window.navigator&&window.navigator.clipboard,L=!1,q=function(){var I=f.getCopyText(),F=f.session.getUndoManager().hasUndo();E.replaceChild(u.buildDom(L?["span",!I&&["span",{class:"ace_mobile-button",action:"selectall"},"Select All"],I&&["span",{class:"ace_mobile-button",action:"copy"},"Copy"],I&&["span",{class:"ace_mobile-button",action:"cut"},"Cut"],w&&["span",{class:"ace_mobile-button",action:"paste"},"Paste"],F&&["span",{class:"ace_mobile-button",action:"undo"},"Undo"],["span",{class:"ace_mobile-button",action:"find"},"Find"],["span",{class:"ace_mobile-button",action:"openCommandPalette"},"Palette"]]:["span"]),E.firstChild)},A=function(I){var F=I.target.getAttribute("action");if(F=="more"||!L)return L=!L,q();F=="paste"?w.readText().then(function(V){f.execCommand(F,V)}):F&&((F=="cut"||F=="copy")&&(w?w.writeText(f.getCopyText()):document.execCommand("copy")),f.execCommand(F)),E.firstChild.style.display="none",L=!1,F!="openCommandPalette"&&f.focus()};E=u.buildDom(["div",{class:"ace_mobile-menu",ontouchstart:function(I){l="menu",I.stopPropagation(),I.preventDefault(),f.textInput.focus()},ontouchend:function(I){I.stopPropagation(),I.preventDefault(),A(I)},onclick:A},["span"],["span",{class:"ace_mobile-button",action:"more"},"..."]],f.container)}function O(){E||x();var w=f.selection.cursor,L=f.renderer.textToScreenCoordinates(w.row,w.column),q=f.renderer.textToScreenCoordinates(0,0).pageX,A=f.renderer.scrollLeft,I=f.container.getBoundingClientRect();E.style.top=L.pageY-I.top-3+"px",L.pageX-I.left=2?f.selection.getLineRange(v.row):f.session.getBracketRange(v);w&&!w.isEmpty()?f.selection.setRange(w):f.selection.selectWord(),l="wait"}a.addListener(r,"contextmenu",function(w){if(!!b){var L=f.textInput.getElement();L.focus()}},f),a.addListener(r,"touchstart",function(w){var L=w.touches;if(c||L.length>1){clearTimeout(c),c=null,o=-1,l="zoom";return}b=f.$mouseHandler.isMousePressed=!0;var q=f.renderer.layerConfig.lineHeight,A=f.renderer.layerConfig.lineHeight,I=w.timeStamp;s=I;var F=L[0],V=F.clientX,R=F.clientY;Math.abs(n-V)+Math.abs(i-R)>q&&(o=-1),n=w.clientX=V,i=w.clientY=R,y=_=0;var B=new g(w,f);if(v=B.getDocumentPosition(),I-o<500&&L.length==1&&!$)C++,w.preventDefault(),w.button=0,T();else{C=0;var N=f.selection.cursor,P=f.selection.isEmpty()?N:f.selection.anchor,j=f.renderer.$cursorLayer.getPixelPosition(N,!0),D=f.renderer.$cursorLayer.getPixelPosition(P,!0),W=f.renderer.scroller.getBoundingClientRect(),H=f.renderer.layerConfig.offset,z=f.renderer.scrollLeft,K=function(se,ue){return se=se/A,ue=ue/q-.75,se*se+ue*ue};if(w.clientXie?"cursor":"anchor"),ie<3.5?l="anchor":Z<3.5?l="cursor":l="scroll",c=setTimeout(k,450)}o=I},f),a.addListener(r,"touchend",function(w){b=f.$mouseHandler.isMousePressed=!1,p&&clearInterval(p),l=="zoom"?(l="",$=0):c?(f.selection.moveToPosition(v),$=0,O()):l=="scroll"?(S(),M()):O(),clearTimeout(c),c=null},f),a.addListener(r,"touchmove",function(w){c&&(clearTimeout(c),c=null);var L=w.touches;if(!(L.length>1||l=="zoom")){var q=L[0],A=n-q.clientX,I=i-q.clientY;if(l=="wait")if(A*A+I*I>4)l="cursor";else return w.preventDefault();n=q.clientX,i=q.clientY,w.clientX=q.clientX,w.clientY=q.clientY;var F=w.timeStamp,V=F-s;if(s=F,l=="scroll"){var R=new g(w,f);R.speed=1,R.wheelX=A,R.wheelY=I,10*Math.abs(A)0)if(ie==16){for(fe=ue;fe-1){for(fe=ue;fe=0&&D[J]==b;J--)P[J]=g}}}function V(N,P,j){if(!(a=N){for(H=W+1;H=N;)H++;for(z=W,K=H-1;z=P.length||(H=j[D-1])!=p&&H!=$||(z=P[D+1])!=p&&z!=$?v:(u&&(z=$),z==H?z:v);case x:return H=D>0?j[D-1]:C,H==p&&D+10&&j[D-1]==p)return p;if(u)return v;for(Z=D+1,K=P.length;Z=1425&&ie<=2303||ie==64286;if(H=P[Z],se&&(H==c||H==_))return c}return D<1||(H=P[D-1])==C?v:j[D-1];case C:return u=!1,r=!0,g;case y:return f=!0,v;case k:case T:case w:case L:case S:u=!1;case q:return v}}function B(N){var P=N.charCodeAt(0),j=P>>8;return j==0?P>191?s:A[P]:j==5?/[\u0591-\u05f4]/.test(N)?c:s:j==6?/[\u0610-\u061a\u064b-\u065f\u06d6-\u06e4\u06e7-\u06ed]/.test(N)?M:/[\u0660-\u0669\u066b-\u066c]/.test(N)?$:P==1642?O:/[\u06f0-\u06f9]/.test(N)?p:_:j==32&&P<=8287?I[P&255]:j==254&&P>=65136?_:v}h.L=s,h.R=c,h.EN=p,h.ON_R=3,h.AN=4,h.R_H=5,h.B=6,h.RLE=7,h.DOT="\xB7",h.doBidiReorder=function(N,P,j){if(N.length<2)return{};var D=N.split(""),W=new Array(D.length),H=new Array(D.length),z=[];g=j?o:i,F(D,z,D.length,P);for(var K=0;K_&&P[K]0&&D[K-1]==="\u0644"&&/\u0622|\u0623|\u0625|\u0627/.test(D[K])&&(z[K-1]=z[K]=h.R_H,K++);D[D.length-1]===h.DOT&&(z[D.length-1]=h.B),D[0]==="\u202B"&&(z[0]=h.RLE);for(var K=0;K=0&&(l=this.session.$docRowCache[i])}return l},f.prototype.getSplitIndex=function(){var l=0,n=this.session.$screenRowCache;if(n.length)for(var i,o=this.session.$getRowCacheIndex(n,this.currentRow);this.currentRow-l>0&&(i=this.session.$getRowCacheIndex(n,this.currentRow-l-1),i===o);)o=i,l++;else l=this.currentRow;return l},f.prototype.updateRowLine=function(l,n){l===void 0&&(l=this.getDocumentRow());var i=l===this.session.getLength()-1,o=i?this.EOF:this.EOL;if(this.wrapIndent=0,this.line=this.session.getLine(l),this.isRtlDir=this.$isRtl||this.line.charAt(0)===this.RLE,this.session.$useWrapMode){var s=this.session.$wrapData[l];s&&(n===void 0&&(n=this.getSplitIndex()),n>0&&s.length?(this.wrapIndent=s.indent,this.wrapOffset=this.wrapIndent*this.charWidths[g.L],this.line=nn?this.session.getOverwrite()?l:l-1:n,o=g.getVisualFromLogicalIdx(i,this.bidiMap),s=this.bidiMap.bidiLevels,c=0;!this.session.getOverwrite()&&l<=n&&s[o]%2!=0&&o++;for(var p=0;pn&&s[o]%2==0&&(c+=this.charWidths[s[o]]),this.wrapIndent&&(c+=this.isRtlDir?-1*this.wrapOffset:this.wrapOffset),this.isRtlDir&&(c+=this.rtlLineOffset),c},f.prototype.getSelections=function(l,n){var i=this.bidiMap,o=i.bidiLevels,s,c=[],p=0,$=Math.min(l,n)-this.wrapIndent,v=Math.max(l,n)-this.wrapIndent,C=!1,y=!1,_=0;this.wrapIndent&&(p+=this.isRtlDir?-1*this.wrapOffset:this.wrapOffset);for(var b,E=0;E=$&&bi+c/2;){if(i+=c,o===s.length-1){c=0;break}c=this.charWidths[s[++o]]}return o>0&&s[o-1]%2!=0&&s[o]%2==0?(l0&&s[o-1]%2==0&&s[o]%2!=0?n=1+(l>i?this.bidiMap.logicalFromVisual[o]:this.bidiMap.logicalFromVisual[o-1]):this.isRtlDir&&o===s.length-1&&c===0&&s[o-1]%2==0||!this.isRtlDir&&o===0&&s[o]%2!=0?n=1+this.bidiMap.logicalFromVisual[o]:(o>0&&s[o-1]%2!=0&&c!==0&&o--,n=this.bidiMap.logicalFromVisual[o]),n===0&&this.isRtlDir&&n++,n+this.wrapIndent},f}();h.BidiHandler=r}),ace.define("ace/selection",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/lib/event_emitter","ace/range"],function(e,h,m){var g=e("./lib/oop"),a=e("./lib/lang"),u=e("./lib/event_emitter").EventEmitter,r=e("./range").Range,f=function(){function l(n){this.session=n,this.doc=n.getDocument(),this.clearSelection(),this.cursor=this.lead=this.doc.createAnchor(0,0),this.anchor=this.doc.createAnchor(0,0),this.$silent=!1;var i=this;this.cursor.on("change",function(o){i.$cursorChanged=!0,i.$silent||i._emit("changeCursor"),!i.$isEmpty&&!i.$silent&&i._emit("changeSelection"),!i.$keepDesiredColumnOnChange&&o.old.column!=o.value.column&&(i.$desiredColumn=null)}),this.anchor.on("change",function(){i.$anchorChanged=!0,!i.$isEmpty&&!i.$silent&&i._emit("changeSelection")})}return l.prototype.isEmpty=function(){return this.$isEmpty||this.anchor.row==this.lead.row&&this.anchor.column==this.lead.column},l.prototype.isMultiLine=function(){return!this.$isEmpty&&this.anchor.row!=this.cursor.row},l.prototype.getCursor=function(){return this.lead.getPosition()},l.prototype.setAnchor=function(n,i){this.$isEmpty=!1,this.anchor.setPosition(n,i)},l.prototype.getAnchor=function(){return this.$isEmpty?this.getSelectionLead():this.anchor.getPosition()},l.prototype.getSelectionLead=function(){return this.lead.getPosition()},l.prototype.isBackwards=function(){var n=this.anchor,i=this.lead;return n.row>i.row||n.row==i.row&&n.column>i.column},l.prototype.getRange=function(){var n=this.anchor,i=this.lead;return this.$isEmpty?r.fromPoints(i,i):this.isBackwards()?r.fromPoints(i,n):r.fromPoints(n,i)},l.prototype.clearSelection=function(){this.$isEmpty||(this.$isEmpty=!0,this._emit("changeSelection"))},l.prototype.selectAll=function(){this.$setSelection(0,0,Number.MAX_VALUE,Number.MAX_VALUE)},l.prototype.setRange=function(n,i){var o=i?n.end:n.start,s=i?n.start:n.end;this.$setSelection(o.row,o.column,s.row,s.column)},l.prototype.$setSelection=function(n,i,o,s){if(!this.$silent){var c=this.$isEmpty,p=this.inMultiSelectMode;this.$silent=!0,this.$cursorChanged=this.$anchorChanged=!1,this.anchor.setPosition(n,i),this.cursor.setPosition(o,s),this.$isEmpty=!r.comparePoints(this.anchor,this.cursor),this.$silent=!1,this.$cursorChanged&&this._emit("changeCursor"),(this.$cursorChanged||this.$anchorChanged||c!=this.$isEmpty||p)&&this._emit("changeSelection")}},l.prototype.$moveSelection=function(n){var i=this.lead;this.$isEmpty&&this.setSelectionAnchor(i.row,i.column),n.call(this)},l.prototype.selectTo=function(n,i){this.$moveSelection(function(){this.moveCursorTo(n,i)})},l.prototype.selectToPosition=function(n){this.$moveSelection(function(){this.moveCursorToPosition(n)})},l.prototype.moveTo=function(n,i){this.clearSelection(),this.moveCursorTo(n,i)},l.prototype.moveToPosition=function(n){this.clearSelection(),this.moveCursorToPosition(n)},l.prototype.selectUp=function(){this.$moveSelection(this.moveCursorUp)},l.prototype.selectDown=function(){this.$moveSelection(this.moveCursorDown)},l.prototype.selectRight=function(){this.$moveSelection(this.moveCursorRight)},l.prototype.selectLeft=function(){this.$moveSelection(this.moveCursorLeft)},l.prototype.selectLineStart=function(){this.$moveSelection(this.moveCursorLineStart)},l.prototype.selectLineEnd=function(){this.$moveSelection(this.moveCursorLineEnd)},l.prototype.selectFileEnd=function(){this.$moveSelection(this.moveCursorFileEnd)},l.prototype.selectFileStart=function(){this.$moveSelection(this.moveCursorFileStart)},l.prototype.selectWordRight=function(){this.$moveSelection(this.moveCursorWordRight)},l.prototype.selectWordLeft=function(){this.$moveSelection(this.moveCursorWordLeft)},l.prototype.getWordRange=function(n,i){if(typeof i=="undefined"){var o=n||this.lead;n=o.row,i=o.column}return this.session.getWordRange(n,i)},l.prototype.selectWord=function(){this.setSelectionRange(this.getWordRange())},l.prototype.selectAWord=function(){var n=this.getCursor(),i=this.session.getAWordRange(n.row,n.column);this.setSelectionRange(i)},l.prototype.getLineRange=function(n,i){var o=typeof n=="number"?n:this.lead.row,s,c=this.session.getFoldLine(o);return c?(o=c.start.row,s=c.end.row):s=o,i===!0?new r(o,0,s,this.session.getLine(s).length):new r(o,0,s+1,0)},l.prototype.selectLine=function(){this.setSelectionRange(this.getLineRange())},l.prototype.moveCursorUp=function(){this.moveCursorBy(-1,0)},l.prototype.moveCursorDown=function(){this.moveCursorBy(1,0)},l.prototype.wouldMoveIntoSoftTab=function(n,i,o){var s=n.column,c=n.column+i;return o<0&&(s=n.column-i,c=n.column),this.session.isTabStop(n)&&this.doc.getLine(n.row).slice(s,c).split(" ").length-1==i},l.prototype.moveCursorLeft=function(){var n=this.lead.getPosition(),i;if(i=this.session.getFoldAt(n.row,n.column,-1))this.moveCursorTo(i.start.row,i.start.column);else if(n.column===0)n.row>0&&this.moveCursorTo(n.row-1,this.doc.getLine(n.row-1).length);else{var o=this.session.getTabSize();this.wouldMoveIntoSoftTab(n,o,-1)&&!this.session.getNavigateWithinSoftTabs()?this.moveCursorBy(0,-o):this.moveCursorBy(0,-1)}},l.prototype.moveCursorRight=function(){var n=this.lead.getPosition(),i;if(i=this.session.getFoldAt(n.row,n.column,1))this.moveCursorTo(i.end.row,i.end.column);else if(this.lead.column==this.doc.getLine(this.lead.row).length)this.lead.row0&&(i.column=s)}}this.moveCursorTo(i.row,i.column)},l.prototype.moveCursorFileEnd=function(){var n=this.doc.getLength()-1,i=this.doc.getLine(n).length;this.moveCursorTo(n,i)},l.prototype.moveCursorFileStart=function(){this.moveCursorTo(0,0)},l.prototype.moveCursorLongWordRight=function(){var n=this.lead.row,i=this.lead.column,o=this.doc.getLine(n),s=o.substring(i);this.session.nonTokenRe.lastIndex=0,this.session.tokenRe.lastIndex=0;var c=this.session.getFoldAt(n,i,1);if(c){this.moveCursorTo(c.end.row,c.end.column);return}if(this.session.nonTokenRe.exec(s)&&(i+=this.session.nonTokenRe.lastIndex,this.session.nonTokenRe.lastIndex=0,s=o.substring(i)),i>=o.length){this.moveCursorTo(n,o.length),this.moveCursorRight(),n0&&this.moveCursorWordLeft();return}this.session.tokenRe.exec(c)&&(i-=this.session.tokenRe.lastIndex,this.session.tokenRe.lastIndex=0),this.moveCursorTo(n,i)},l.prototype.$shortWordEndIndex=function(n){var i=0,o,s=/\s/,c=this.session.tokenRe;if(c.lastIndex=0,this.session.tokenRe.exec(n))i=this.session.tokenRe.lastIndex;else{for(;(o=n[i])&&s.test(o);)i++;if(i<1){for(c.lastIndex=0;(o=n[i])&&!c.test(o);)if(c.lastIndex=0,i++,s.test(o))if(i>2){i--;break}else{for(;(o=n[i])&&s.test(o);)i++;if(i>2)break}}}return c.lastIndex=0,i},l.prototype.moveCursorShortWordRight=function(){var n=this.lead.row,i=this.lead.column,o=this.doc.getLine(n),s=o.substring(i),c=this.session.getFoldAt(n,i,1);if(c)return this.moveCursorTo(c.end.row,c.end.column);if(i==o.length){var p=this.doc.getLength();do n++,s=this.doc.getLine(n);while(n0&&/^\s*$/.test(s));i=s.length,/\s+$/.test(s)||(s="")}var c=a.stringReverse(s),p=this.$shortWordEndIndex(c);return this.moveCursorTo(n,i-p)},l.prototype.moveCursorWordRight=function(){this.session.$selectLongWords?this.moveCursorLongWordRight():this.moveCursorShortWordRight()},l.prototype.moveCursorWordLeft=function(){this.session.$selectLongWords?this.moveCursorLongWordLeft():this.moveCursorShortWordLeft()},l.prototype.moveCursorBy=function(n,i){var o=this.session.documentToScreenPosition(this.lead.row,this.lead.column),s;if(i===0&&(n!==0&&(this.session.$bidiHandler.isBidiRow(o.row,this.lead.row)?(s=this.session.$bidiHandler.getPosLeft(o.column),o.column=Math.round(s/this.session.$bidiHandler.charWidths[0])):s=o.column*this.session.$bidiHandler.charWidths[0]),this.$desiredColumn?o.column=this.$desiredColumn:this.$desiredColumn=o.column),n!=0&&this.session.lineWidgets&&this.session.lineWidgets[this.lead.row]){var c=this.session.lineWidgets[this.lead.row];n<0?n-=c.rowsAbove||0:n>0&&(n+=c.rowCount-(c.rowsAbove||0))}var p=this.session.screenToDocumentPosition(o.row+n,o.column,s);n!==0&&i===0&&p.row===this.lead.row&&p.column===this.lead.column,this.moveCursorTo(p.row,p.column+i,i===0)},l.prototype.moveCursorToPosition=function(n){this.moveCursorTo(n.row,n.column)},l.prototype.moveCursorTo=function(n,i,o){var s=this.session.getFoldAt(n,i,1);s&&(n=s.start.row,i=s.start.column),this.$keepDesiredColumnOnChange=!0;var c=this.session.getLine(n);/[\uDC00-\uDFFF]/.test(c.charAt(i))&&c.charAt(i-1)&&(this.lead.row==n&&this.lead.column==i+1?i=i-1:i=i+1),this.lead.setPosition(n,i),this.$keepDesiredColumnOnChange=!1,o||(this.$desiredColumn=null)},l.prototype.moveCursorToScreen=function(n,i,o){var s=this.session.screenToDocumentPosition(n,i);this.moveCursorTo(s.row,s.column,o)},l.prototype.detach=function(){this.lead.detach(),this.anchor.detach()},l.prototype.fromOrientedRange=function(n){this.setSelectionRange(n,n.cursor==n.start),this.$desiredColumn=n.desiredColumn||this.$desiredColumn},l.prototype.toOrientedRange=function(n){var i=this.getRange();return n?(n.start.column=i.start.column,n.start.row=i.start.row,n.end.column=i.end.column,n.end.row=i.end.row):n=i,n.cursor=this.isBackwards()?n.start:n.end,n.desiredColumn=this.$desiredColumn,n},l.prototype.getRangeOfMovements=function(n){var i=this.getCursor();try{n(this);var o=this.getCursor();return r.fromPoints(i,o)}catch{return r.fromPoints(i,i)}finally{this.moveCursorToPosition(i)}},l.prototype.toJSON=function(){if(this.rangeCount)var n=this.ranges.map(function(i){var o=i.clone();return o.isBackwards=i.cursor==i.start,o});else{var n=this.getRange();n.isBackwards=this.isBackwards()}return n},l.prototype.fromJSON=function(n){if(n.start==null)if(this.rangeList&&n.length>1){this.toSingleRange(n[0]);for(var i=n.length;i--;){var o=r.fromPoints(n[i].start,n[i].end);n[i].isBackwards&&(o.cursor=o.start),this.addRange(o,!0)}return}else n=n[0];this.rangeList&&this.toSingleRange(n),this.setSelectionRange(n,n.isBackwards)},l.prototype.isEqual=function(n){if((n.length||this.rangeCount)&&n.length!=this.rangeCount)return!1;if(!n.length||!this.ranges)return this.getRange().isEqual(n);for(var i=this.ranges.length;i--;)if(!this.ranges[i].isEqual(n[i]))return!1;return!0},l}();f.prototype.setSelectionAnchor=f.prototype.setAnchor,f.prototype.getSelectionAnchor=f.prototype.getAnchor,f.prototype.setSelectionRange=f.prototype.setRange,g.implement(f.prototype,u),h.Selection=f}),ace.define("ace/tokenizer",["require","exports","module","ace/lib/report_error"],function(e,h,m){var g=e("./lib/report_error").reportError,a=2e3,u=function(){function r(f){this.splitRegex,this.states=f,this.regExps={},this.matchMappings={};for(var l in this.states){for(var n=this.states[l],i=[],o=0,s=this.matchMappings[l]={defaultToken:"text"},c="g",p=[],$=0;$1?v.onMatch=this.$applyToken:v.onMatch=v.token),y>1&&(/\\\d/.test(v.regex)?C=v.regex.replace(/\\([0-9]+)/g,function(_,b){return"\\"+(parseInt(b,10)+o+1)}):(y=1,C=this.removeCapturingGroups(v.regex)),!v.splitRegex&&typeof v.token!="string"&&p.push(v)),s[o]=$,o+=y,i.push(C),v.onMatch||(v.onMatch=null)}}i.length||(s[0]=0,i.push("$")),p.forEach(function(_){_.splitRegex=this.createSplitterRegexp(_.regex,c)},this),this.regExps[l]=new RegExp("("+i.join(")|(")+")|($)",c)}}return r.prototype.$setMaxTokenCount=function(f){a=f|0},r.prototype.$applyToken=function(f){var l=this.splitRegex.exec(f).slice(1),n=this.token.apply(this,l);if(typeof n=="string")return[{type:n,value:f}];for(var i=[],o=0,s=n.length;ov){var O=f.substring(v,x-E.length);y.type==_?y.value+=O:(y.type&&$.push(y),y={type:_,value:O})}for(var M=0;Ma){for(C>2*f.length&&this.reportError("infinite loop with in ace tokenizer",{startState:l,line:f});v1&&n[0]!==i&&n.unshift("#tmp",i),{tokens:$,state:n.length?n:i}},r}();u.prototype.reportError=g,h.Tokenizer=u}),ace.define("ace/mode/text_highlight_rules",["require","exports","module","ace/lib/deep_copy"],function(e,h,m){var g=e("../lib/deep_copy").deepCopy,a;a=function(){this.$rules={start:[{token:"empty_line",regex:"^$"},{defaultToken:"text"}]}},function(){this.addRules=function(f,l){if(!l){for(var n in f)this.$rules[n]=f[n];return}for(var n in f){for(var i=f[n],o=0;o=this.$rowTokens.length;){if(this.$row+=1,r||(r=this.$session.getLength()),this.$row>=r)return this.$row=r-1,null;this.$rowTokens=this.$session.getTokens(this.$row),this.$tokenIndex=0}return this.$rowTokens[this.$tokenIndex]},u.prototype.getCurrentToken=function(){return this.$rowTokens[this.$tokenIndex]},u.prototype.getCurrentTokenRow=function(){return this.$row},u.prototype.getCurrentTokenColumn=function(){var r=this.$rowTokens,f=this.$tokenIndex,l=r[f].start;if(l!==void 0)return l;for(l=0;f>0;)f-=1,l+=r[f].value.length;return l},u.prototype.getCurrentTokenPosition=function(){return{row:this.$row,column:this.getCurrentTokenColumn()}},u.prototype.getCurrentTokenRange=function(){var r=this.$rowTokens[this.$tokenIndex],f=this.getCurrentTokenColumn();return new g(this.$row,f,this.$row,f+r.value.length)},u}();h.TokenIterator=a}),ace.define("ace/mode/behaviour/cstyle",["require","exports","module","ace/lib/oop","ace/mode/behaviour","ace/token_iterator","ace/lib/lang"],function(e,h,m){var g=e("../../lib/oop"),a=e("../behaviour").Behaviour,u=e("../../token_iterator").TokenIterator,r=e("../../lib/lang"),f=["text","paren.rparen","rparen","paren","punctuation.operator"],l=["text","paren.rparen","rparen","paren","punctuation.operator","comment"],n,i={},o={'"':'"',"'":"'"},s=function($){var v=-1;if($.multiSelect&&(v=$.selection.index,i.rangeCount!=$.multiSelect.rangeCount&&(i={rangeCount:$.multiSelect.rangeCount})),i[v])return n=i[v];n=i[v]={autoInsertedBrackets:0,autoInsertedRow:-1,autoInsertedLineEnd:"",maybeInsertedBrackets:0,maybeInsertedRow:-1,maybeInsertedLineStart:"",maybeInsertedLineEnd:""}},c=function($,v,C,y){var _=$.end.row-$.start.row;return{text:C+v+y,selection:[0,$.start.column+1,_,$.end.column+(_?0:1)]}},p;p=function($){$=$||{},this.add("braces","insertion",function(v,C,y,_,b){var E=y.getCursorPosition(),x=_.doc.getLine(E.row);if(b=="{"){s(y);var O=y.getSelectionRange(),M=_.doc.getTextRange(O);if(M!==""&&M!=="{"&&y.getWrapBehavioursEnabled())return c(O,M,"{","}");if(p.isSaneInsertion(y,_))return/[\]\}\)]/.test(x[E.column])||y.inMultiSelectMode||$.braces?(p.recordAutoInsert(y,_,"}"),{text:"{}",selection:[1,1]}):(p.recordMaybeInsert(y,_,"{"),{text:"{",selection:[1,1]})}else if(b=="}"){s(y);var k=x.substring(E.column,E.column+1);if(k=="}"){var T=_.$findOpeningBracket("}",{column:E.column+1,row:E.row});if(T!==null&&p.isAutoInsertedClosing(E,x,b))return p.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}else if(b==` +`||b==`\r +`){s(y);var S="";p.isMaybeInsertedClosing(E,x)&&(S=r.stringRepeat("}",n.maybeInsertedBrackets),p.clearMaybeInsertedClosing());var k=x.substring(E.column,E.column+1);if(k==="}"){var w=_.findMatchingBracket({row:E.row,column:E.column+1},"}");if(!w)return null;var L=this.$getIndent(_.getLine(w.row))}else if(S)var L=this.$getIndent(x);else{p.clearMaybeInsertedClosing();return}var q=L+_.getTabString();return{text:` +`+q+` +`+L+S,selection:[1,q.length,1,q.length]}}else p.clearMaybeInsertedClosing()}),this.add("braces","deletion",function(v,C,y,_,b){var E=_.doc.getTextRange(b);if(!b.isMultiLine()&&E=="{"){s(y);var x=_.doc.getLine(b.start.row),O=x.substring(b.end.column,b.end.column+1);if(O=="}")return b.end.column++,b;n.maybeInsertedBrackets--}}),this.add("parens","insertion",function(v,C,y,_,b){if(b=="("){s(y);var E=y.getSelectionRange(),x=_.doc.getTextRange(E);if(x!==""&&y.getWrapBehavioursEnabled())return c(E,x,"(",")");if(p.isSaneInsertion(y,_))return p.recordAutoInsert(y,_,")"),{text:"()",selection:[1,1]}}else if(b==")"){s(y);var O=y.getCursorPosition(),M=_.doc.getLine(O.row),k=M.substring(O.column,O.column+1);if(k==")"){var T=_.$findOpeningBracket(")",{column:O.column+1,row:O.row});if(T!==null&&p.isAutoInsertedClosing(O,M,b))return p.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}}),this.add("parens","deletion",function(v,C,y,_,b){var E=_.doc.getTextRange(b);if(!b.isMultiLine()&&E=="("){s(y);var x=_.doc.getLine(b.start.row),O=x.substring(b.start.column+1,b.start.column+2);if(O==")")return b.end.column++,b}}),this.add("brackets","insertion",function(v,C,y,_,b){if(b=="["){s(y);var E=y.getSelectionRange(),x=_.doc.getTextRange(E);if(x!==""&&y.getWrapBehavioursEnabled())return c(E,x,"[","]");if(p.isSaneInsertion(y,_))return p.recordAutoInsert(y,_,"]"),{text:"[]",selection:[1,1]}}else if(b=="]"){s(y);var O=y.getCursorPosition(),M=_.doc.getLine(O.row),k=M.substring(O.column,O.column+1);if(k=="]"){var T=_.$findOpeningBracket("]",{column:O.column+1,row:O.row});if(T!==null&&p.isAutoInsertedClosing(O,M,b))return p.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}}),this.add("brackets","deletion",function(v,C,y,_,b){var E=_.doc.getTextRange(b);if(!b.isMultiLine()&&E=="["){s(y);var x=_.doc.getLine(b.start.row),O=x.substring(b.start.column+1,b.start.column+2);if(O=="]")return b.end.column++,b}}),this.add("string_dquotes","insertion",function(v,C,y,_,b){var E=_.$mode.$quotes||o;if(b.length==1&&E[b]){if(this.lineCommentStart&&this.lineCommentStart.indexOf(b)!=-1)return;s(y);var x=b,O=y.getSelectionRange(),M=_.doc.getTextRange(O);if(M!==""&&(M.length!=1||!E[M])&&y.getWrapBehavioursEnabled())return c(O,M,x,x);if(!M){var k=y.getCursorPosition(),T=_.doc.getLine(k.row),S=T.substring(k.column-1,k.column),w=T.substring(k.column,k.column+1),L=_.getTokenAt(k.row,k.column),q=_.getTokenAt(k.row,k.column+1);if(S=="\\"&&L&&/escape/.test(L.type))return null;var A=L&&/string|escape/.test(L.type),I=!q||/string|escape/.test(q.type),F;if(w==x)F=A!==I,F&&/string\.end/.test(q.type)&&(F=!1);else{if(A&&!I||A&&I)return null;var V=_.$mode.tokenRe;V.lastIndex=0;var R=V.test(S);V.lastIndex=0;var B=V.test(w),N=_.$mode.$pairQuotesAfter,P=N&&N[x]&&N[x].test(S);if(!P&&R||B||w&&!/[\s;,.})\]\\]/.test(w))return null;var j=T[k.column-2];if(S==x&&(j==x||V.test(j)))return null;F=!0}return{text:F?x+x:"",selection:[1,1]}}}}),this.add("string_dquotes","deletion",function(v,C,y,_,b){var E=_.$mode.$quotes||o,x=_.doc.getTextRange(b);if(!b.isMultiLine()&&E.hasOwnProperty(x)){s(y);var O=_.doc.getLine(b.start.row),M=O.substring(b.start.column+1,b.start.column+2);if(M==x)return b.end.column++,b}}),$.closeDocComment!==!1&&this.add("doc comment end","insertion",function(v,C,y,_,b){if(v==="doc-start"&&(b===` +`||b===`\r +`)&&y.selection.isEmpty()){var E=y.getCursorPosition(),x=_.doc.getLine(E.row),O=_.doc.getLine(E.row+1),M=this.$getIndent(x);if(/\s*\*/.test(O))return/^\s*\*/.test(x)?{text:b+M+"* ",selection:[1,3+M.length,1,3+M.length]}:{text:b+M+" * ",selection:[1,3+M.length,1,3+M.length]};if(/\/\*\*/.test(x.substring(0,E.column)))return{text:b+M+" * "+b+" "+M+"*/",selection:[1,4+M.length,1,4+M.length]}}})},p.isSaneInsertion=function($,v){var C=$.getCursorPosition(),y=new u(v,C.row,C.column);if(!this.$matchTokenType(y.getCurrentToken()||"text",f)){if(/[)}\]]/.test($.session.getLine(C.row)[C.column]))return!0;var _=new u(v,C.row,C.column+1);if(!this.$matchTokenType(_.getCurrentToken()||"text",f))return!1}return y.stepForward(),y.getCurrentTokenRow()!==C.row||this.$matchTokenType(y.getCurrentToken()||"text",l)},p.$matchTokenType=function($,v){return v.indexOf($.type||$)>-1},p.recordAutoInsert=function($,v,C){var y=$.getCursorPosition(),_=v.doc.getLine(y.row);this.isAutoInsertedClosing(y,_,n.autoInsertedLineEnd[0])||(n.autoInsertedBrackets=0),n.autoInsertedRow=y.row,n.autoInsertedLineEnd=C+_.substr(y.column),n.autoInsertedBrackets++},p.recordMaybeInsert=function($,v,C){var y=$.getCursorPosition(),_=v.doc.getLine(y.row);this.isMaybeInsertedClosing(y,_)||(n.maybeInsertedBrackets=0),n.maybeInsertedRow=y.row,n.maybeInsertedLineStart=_.substr(0,y.column)+C,n.maybeInsertedLineEnd=_.substr(y.column),n.maybeInsertedBrackets++},p.isAutoInsertedClosing=function($,v,C){return n.autoInsertedBrackets>0&&$.row===n.autoInsertedRow&&C===n.autoInsertedLineEnd[0]&&v.substr($.column)===n.autoInsertedLineEnd},p.isMaybeInsertedClosing=function($,v){return n.maybeInsertedBrackets>0&&$.row===n.maybeInsertedRow&&v.substr($.column)===n.maybeInsertedLineEnd&&v.substr(0,$.column)==n.maybeInsertedLineStart},p.popAutoInsertedClosing=function(){n.autoInsertedLineEnd=n.autoInsertedLineEnd.substr(1),n.autoInsertedBrackets--},p.clearMaybeInsertedClosing=function(){n&&(n.maybeInsertedBrackets=0,n.maybeInsertedRow=-1)},g.inherits(p,a),h.CstyleBehaviour=p}),ace.define("ace/unicode",["require","exports","module"],function(e,h,m){for(var g=[48,9,8,25,5,0,2,25,48,0,11,0,5,0,6,22,2,30,2,457,5,11,15,4,8,0,2,0,18,116,2,1,3,3,9,0,2,2,2,0,2,19,2,82,2,138,2,4,3,155,12,37,3,0,8,38,10,44,2,0,2,1,2,1,2,0,9,26,6,2,30,10,7,61,2,9,5,101,2,7,3,9,2,18,3,0,17,58,3,100,15,53,5,0,6,45,211,57,3,18,2,5,3,11,3,9,2,1,7,6,2,2,2,7,3,1,3,21,2,6,2,0,4,3,3,8,3,1,3,3,9,0,5,1,2,4,3,11,16,2,2,5,5,1,3,21,2,6,2,1,2,1,2,1,3,0,2,4,5,1,3,2,4,0,8,3,2,0,8,15,12,2,2,8,2,2,2,21,2,6,2,1,2,4,3,9,2,2,2,2,3,0,16,3,3,9,18,2,2,7,3,1,3,21,2,6,2,1,2,4,3,8,3,1,3,2,9,1,5,1,2,4,3,9,2,0,17,1,2,5,4,2,2,3,4,1,2,0,2,1,4,1,4,2,4,11,5,4,4,2,2,3,3,0,7,0,15,9,18,2,2,7,2,2,2,22,2,9,2,4,4,7,2,2,2,3,8,1,2,1,7,3,3,9,19,1,2,7,2,2,2,22,2,9,2,4,3,8,2,2,2,3,8,1,8,0,2,3,3,9,19,1,2,7,2,2,2,22,2,15,4,7,2,2,2,3,10,0,9,3,3,9,11,5,3,1,2,17,4,23,2,8,2,0,3,6,4,0,5,5,2,0,2,7,19,1,14,57,6,14,2,9,40,1,2,0,3,1,2,0,3,0,7,3,2,6,2,2,2,0,2,0,3,1,2,12,2,2,3,4,2,0,2,5,3,9,3,1,35,0,24,1,7,9,12,0,2,0,2,0,5,9,2,35,5,19,2,5,5,7,2,35,10,0,58,73,7,77,3,37,11,42,2,0,4,328,2,3,3,6,2,0,2,3,3,40,2,3,3,32,2,3,3,6,2,0,2,3,3,14,2,56,2,3,3,66,5,0,33,15,17,84,13,619,3,16,2,25,6,74,22,12,2,6,12,20,12,19,13,12,2,2,2,1,13,51,3,29,4,0,5,1,3,9,34,2,3,9,7,87,9,42,6,69,11,28,4,11,5,11,11,39,3,4,12,43,5,25,7,10,38,27,5,62,2,28,3,10,7,9,14,0,89,75,5,9,18,8,13,42,4,11,71,55,9,9,4,48,83,2,2,30,14,230,23,280,3,5,3,37,3,5,3,7,2,0,2,0,2,0,2,30,3,52,2,6,2,0,4,2,2,6,4,3,3,5,5,12,6,2,2,6,67,1,20,0,29,0,14,0,17,4,60,12,5,0,4,11,18,0,5,0,3,9,2,0,4,4,7,0,2,0,2,0,2,3,2,10,3,3,6,4,5,0,53,1,2684,46,2,46,2,132,7,6,15,37,11,53,10,0,17,22,10,6,2,6,2,6,2,6,2,6,2,6,2,6,2,6,2,31,48,0,470,1,36,5,2,4,6,1,5,85,3,1,3,2,2,89,2,3,6,40,4,93,18,23,57,15,513,6581,75,20939,53,1164,68,45,3,268,4,27,21,31,3,13,13,1,2,24,9,69,11,1,38,8,3,102,3,1,111,44,25,51,13,68,12,9,7,23,4,0,5,45,3,35,13,28,4,64,15,10,39,54,10,13,3,9,7,22,4,1,5,66,25,2,227,42,2,1,3,9,7,11171,13,22,5,48,8453,301,3,61,3,105,39,6,13,4,6,11,2,12,2,4,2,0,2,1,2,1,2,107,34,362,19,63,3,53,41,11,5,15,17,6,13,1,25,2,33,4,2,134,20,9,8,25,5,0,2,25,12,88,4,5,3,5,3,5,3,2],a=0,u=[],r=0;r2?j%b!=b-1:j%b==0}}else{if(!this.blockComment)return!1;var x=this.blockComment.start,O=this.blockComment.end,M=new RegExp("^(\\s*)(?:"+l.escapeRegExp(x)+")"),k=new RegExp("(?:"+l.escapeRegExp(O)+")\\s*$"),T=function(F,V){w(F,V)||(!C||/\S/.test(F))&&(v.insertInLine({row:V,column:F.length},O),v.insertInLine({row:V,column:_},x))},S=function(F,V){var R;(R=F.match(k))&&v.removeInLine(V,F.length-R[0].length,F.length),(R=F.match(M))&&v.removeInLine(V,R[1].length,R[0].length)},w=function(F,V){if(M.test(F))return!0;for(var R=c.getTokens(V),B=0;BF.length&&(I=F.length)}),_==1/0&&(_=I,C=!1,y=!1),E&&_%b!=0&&(_=Math.floor(_/b)*b),A(y?S:T)},this.toggleBlockComment=function(s,c,p,$){var v=this.blockComment;if(!!v){!v.start&&v[0]&&(v=v[0]);var C=new n(c,$.row,$.column),y=C.getCurrentToken();c.selection;var _=c.selection.toOrientedRange(),b,E;if(y&&/comment/.test(y.type)){for(var x,O;y&&/comment/.test(y.type);){var M=y.value.indexOf(v.start);if(M!=-1){var k=C.getCurrentTokenRow(),T=C.getCurrentTokenColumn()+M;x=new i(k,T,k,T+v.start.length);break}y=C.stepBackward()}for(var C=new n(c,$.row,$.column),y=C.getCurrentToken();y&&/comment/.test(y.type);){var M=y.value.indexOf(v.end);if(M!=-1){var k=C.getCurrentTokenRow(),T=C.getCurrentTokenColumn()+M;O=new i(k,T,k,T+v.end.length);break}y=C.stepForward()}O&&c.remove(O),x&&(c.remove(x),b=x.start.row,E=-v.start.length)}else E=v.start.length,b=p.start.row,c.insert(p.end,v.end),c.insert(p.start,v.start);_.start.row==b&&(_.start.column+=E),_.end.row==b&&(_.end.column+=E),c.selection.fromOrientedRange(_)}},this.getNextLineIndent=function(s,c,p){return this.$getIndent(c)},this.checkOutdent=function(s,c,p){return!1},this.autoOutdent=function(s,c,p){},this.$getIndent=function(s){return s.match(/^\s*/)[0]},this.createWorker=function(s){return null},this.createModeDelegates=function(s){this.$embeds=[],this.$modes={};for(var c in s)if(s[c]){var p=s[c],$=p.prototype.$id,v=g.$modes[$];v||(g.$modes[$]=v=new p),g.$modes[c]||(g.$modes[c]=v),this.$embeds.push(c),this.$modes[c]=v}for(var C=["toggleBlockComment","toggleCommentLines","getNextLineIndent","checkOutdent","autoOutdent","transformAction","getCompletions"],y=function(b){(function(E){var x=C[b],O=E[x];E[C[b]]=function(){return this.$delegator(x,arguments,O)}})(_)},_=this,c=0;cthis.row)){var i=f(n,{row:this.row,column:this.column},this.$insertRight);this.setPosition(i.row,i.column,!0)}},l.prototype.setPosition=function(n,i,o){var s;if(o?s={row:n,column:i}:s=this.$clipPositionToDocument(n,i),!(this.row==s.row&&this.column==s.column)){var c={row:this.row,column:this.column};this.row=s.row,this.column=s.column,this._signal("change",{old:c,value:s})}},l.prototype.detach=function(){this.document.off("change",this.$onChange)},l.prototype.attach=function(n){this.document=n||this.document,this.document.on("change",this.$onChange)},l.prototype.$clipPositionToDocument=function(n,i){var o={};return n>=this.document.getLength()?(o.row=Math.max(0,this.document.getLength()-1),o.column=this.document.getLine(o.row).length):n<0?(o.row=0,o.column=0):(o.row=n,o.column=Math.min(this.document.getLine(o.row).length,Math.max(0,i))),i<0&&(o.column=0),o},l}();u.prototype.$insertRight=!1,g.implement(u.prototype,a);function r(l,n,i){var o=i?l.column<=n.column:l.column=s&&(i=s-1,o=void 0);var c=this.getLine(i);return o==null&&(o=c.length),o=Math.min(Math.max(o,0),c.length),{row:i,column:o}},n.prototype.clonePos=function(i){return{row:i.row,column:i.column}},n.prototype.pos=function(i,o){return{row:i,column:o}},n.prototype.$clipPosition=function(i){var o=this.getLength();return i.row>=o?(i.row=Math.max(0,o-1),i.column=this.getLine(o-1).length):(i.row=Math.max(0,i.row),i.column=Math.min(Math.max(i.column,0),this.getLine(i.row).length)),i},n.prototype.insertFullLines=function(i,o){i=Math.min(Math.max(i,0),this.getLength());var s=0;i0,c=o=0&&this.applyDelta({start:this.pos(i,this.getLine(i).length),end:this.pos(i+1,0),action:"remove",lines:["",""]})},n.prototype.replace=function(i,o){if(i instanceof r||(i=r.fromPoints(i.start,i.end)),o.length===0&&i.isEmpty())return i.start;if(o==this.getTextRange(i))return i.end;this.remove(i);var s;return o?s=this.insert(i.start,o):s=i.start,s},n.prototype.applyDeltas=function(i){for(var o=0;o=0;o--)this.revertDelta(i[o])},n.prototype.applyDelta=function(i,o){var s=i.action=="insert";(s?i.lines.length<=1&&!i.lines[0]:!r.comparePoints(i.start,i.end))||(s&&i.lines.length>2e4?this.$splitAndapplyLargeDelta(i,2e4):(a(this.$lines,i,o),this._signal("change",i)))},n.prototype.$safeApplyDelta=function(i){var o=this.$lines.length;(i.action=="remove"&&i.start.row20){n.running=setTimeout(n.$worker,20);break}}n.currentLine=o,s==-1&&(s=o),p<=s&&n.fireUpdateEvent(p,s)}}}return r.prototype.setTokenizer=function(f){this.tokenizer=f,this.lines=[],this.states=[],this.start(0)},r.prototype.setDocument=function(f){this.doc=f,this.lines=[],this.states=[],this.stop()},r.prototype.fireUpdateEvent=function(f,l){var n={first:f,last:l};this._signal("update",{data:n})},r.prototype.start=function(f){this.currentLine=Math.min(f||0,this.currentLine,this.doc.getLength()),this.lines.splice(this.currentLine,this.lines.length),this.states.splice(this.currentLine,this.states.length),this.stop(),this.running=setTimeout(this.$worker,700)},r.prototype.scheduleStart=function(){this.running||(this.running=setTimeout(this.$worker,700))},r.prototype.$updateOnChange=function(f){var l=f.start.row,n=f.end.row-l;if(n===0)this.lines[l]=null;else if(f.action=="remove")this.lines.splice(l,n+1,null),this.states.splice(l,n+1,null);else{var i=Array(n+1);i.unshift(l,1),this.lines.splice.apply(this.lines,i),this.states.splice.apply(this.states,i)}this.currentLine=Math.min(l,this.currentLine,this.doc.getLength()),this.stop()},r.prototype.stop=function(){this.running&&clearTimeout(this.running),this.running=!1},r.prototype.getTokens=function(f){return this.lines[f]||this.$tokenizeRow(f)},r.prototype.getState=function(f){return this.currentLine==f&&this.$tokenizeRow(f),this.states[f]||"start"},r.prototype.$tokenizeRow=function(f){var l=this.doc.getLine(f),n=this.states[f-1],i=this.tokenizer.getLineTokens(l,n,f);return this.states[f]+""!=i.state+""?(this.states[f]=i.state,this.lines[f+1]=null,this.currentLine>f+1&&(this.currentLine=f+1)):this.currentLine==f&&(this.currentLine=f+1),this.lines[f]=i.tokens},r.prototype.cleanup=function(){this.running=!1,this.lines=[],this.states=[],this.currentLine=0,this.removeAllListeners()},r}();g.implement(u.prototype,a),h.BackgroundTokenizer=u}),ace.define("ace/search_highlight",["require","exports","module","ace/lib/lang","ace/range"],function(e,h,m){var g=e("./lib/lang"),a=e("./range").Range,u=function(){function r(f,l,n){n===void 0&&(n="text"),this.setRegexp(f),this.clazz=l,this.type=n}return r.prototype.setRegexp=function(f){this.regExp+""!=f+""&&(this.regExp=f,this.cache=[])},r.prototype.update=function(f,l,n,i){if(!!this.regExp)for(var o=i.firstRow,s=i.lastRow,c={},p=o;p<=s;p++){var $=this.cache[p];$==null&&($=g.getMatchOffsets(n.getLine(p),this.regExp),$.length>this.MAX_RANGES&&($=$.slice(0,this.MAX_RANGES)),$=$.map(function(_){return new a(p,_.offset,p,_.offset+_.length)}),this.cache[p]=$.length?$:"");for(var v=$.length;v--;){var C=$[v].toScreenRange(n),y=C.toString();c[y]||(c[y]=!0,l.drawSingleLineMarker(f,C,this.clazz,i))}}},r}();u.prototype.MAX_RANGES=500,h.SearchHighlight=u}),ace.define("ace/undomanager",["require","exports","module","ace/range"],function(e,h,m){var g=function(){function _(){this.$keepRedoStack,this.$maxRev=0,this.$fromUndo=!1,this.$undoDepth=1/0,this.reset()}return _.prototype.addSession=function(b){this.$session=b},_.prototype.add=function(b,E,x){if(!this.$fromUndo&&b!=this.$lastDelta){if(this.$keepRedoStack||(this.$redoStack.length=0),E===!1||!this.lastDeltas){this.lastDeltas=[];var O=this.$undoStack.length;O>this.$undoDepth-1&&this.$undoStack.splice(0,O-this.$undoDepth+1),this.$undoStack.push(this.lastDeltas),b.id=this.$rev=++this.$maxRev}(b.action=="remove"||b.action=="insert")&&(this.$lastDelta=b),this.lastDeltas.push(b)}},_.prototype.addSelection=function(b,E){this.selections.push({value:b,rev:E||this.$rev})},_.prototype.startNewGroup=function(){return this.lastDeltas=null,this.$rev},_.prototype.markIgnored=function(b,E){E==null&&(E=this.$rev+1);for(var x=this.$undoStack,O=x.length;O--;){var M=x[O][0];if(M.id<=b)break;M.id0},_.prototype.canRedo=function(){return this.$redoStack.length>0},_.prototype.bookmark=function(b){b==null&&(b=this.$rev),this.mark=b},_.prototype.isAtBookmark=function(){return this.$rev===this.mark},_.prototype.toJSON=function(){return{$redoStack:this.$redoStack,$undoStack:this.$undoStack}},_.prototype.fromJSON=function(b){this.reset(),this.$undoStack=b.$undoStack,this.$redoStack=b.$redoStack},_.prototype.$prettyPrint=function(b){return b?n(b):n(this.$undoStack)+` +--- +`+n(this.$redoStack)},_}();g.prototype.hasUndo=g.prototype.canUndo,g.prototype.hasRedo=g.prototype.canRedo,g.prototype.isClean=g.prototype.isAtBookmark,g.prototype.markClean=g.prototype.bookmark;function a(_,b){for(var E=b;E--;){var x=_[E];if(x&&!x[0].ignore){for(;E"+_.end.row+":"+_.end.column}function o(_,b){var E=_.action=="insert",x=b.action=="insert";if(E&&x)if(r(b.start,_.end)>=0)p(b,_,-1);else if(r(b.start,_.start)<=0)p(_,b,1);else return null;else if(E&&!x)if(r(b.start,_.end)>=0)p(b,_,-1);else if(r(b.end,_.start)<=0)p(_,b,-1);else return null;else if(!E&&x)if(r(b.start,_.start)>=0)p(b,_,1);else if(r(b.start,_.start)<=0)p(_,b,1);else return null;else if(!E&&!x)if(r(b.start,_.start)>=0)p(b,_,1);else if(r(b.end,_.start)<=0)p(_,b,-1);else return null;return[b,_]}function s(_,b){for(var E=_.length;E--;)for(var x=0;x=0?p(_,b,-1):(r(_.start,b.start)<=0||p(_,u.fromPoints(b.start,_.start),-1),p(b,_,1));else if(!E&&x)r(b.start,_.end)>=0?p(b,_,-1):(r(b.start,_.start)<=0||p(b,u.fromPoints(_.start,b.start),-1),p(_,b,1));else if(!E&&!x)if(r(b.start,_.end)>=0)p(b,_,-1);else if(r(b.end,_.start)<=0)p(_,b,-1);else{var O,M;return r(_.start,b.start)<0&&(O=_,_=v(_,b.start)),r(_.end,b.end)>0&&(M=v(_,b.end)),$(b.end,_.start,_.end,-1),M&&!O&&(_.lines=M.lines,_.start=M.start,_.end=M.end,M=_),[b,O,M].filter(Boolean)}return[b,_]}function p(_,b,E){$(_.start,b.start,b.end,E),$(_.end,b.start,b.end,E)}function $(_,b,E,x){_.row==(x==1?b:E).row&&(_.column+=x*(E.column-b.column)),_.row+=x*(E.row-b.row)}function v(_,b){var E=_.lines,x=_.end;_.end=f(b);var O=_.end.row-_.start.row,M=E.splice(O,E.length),k=O?b.column:b.column-_.start.column;E.push(M[0].substring(0,k)),M[0]=M[0].substr(k);var T={start:f(b),end:x,lines:M,action:_.action};return T}function C(_,b){b=l(b);for(var E=_.length;E--;){for(var x=_[E],O=0;Othis.endRow)throw new Error("Can't add a fold to this FoldLine as it has no connection");this.folds.push(r),this.folds.sort(function(f,l){return-f.range.compareEnd(l.start.row,l.start.column)}),this.range.compareEnd(r.start.row,r.start.column)>0?(this.end.row=r.end.row,this.end.column=r.end.column):this.range.compareStart(r.end.row,r.end.column)<0&&(this.start.row=r.start.row,this.start.column=r.start.column)}else if(r.start.row==this.end.row)this.folds.push(r),this.end.row=r.end.row,this.end.column=r.end.column;else if(r.end.row==this.start.row)this.folds.unshift(r),this.start.row=r.start.row,this.start.column=r.start.column;else throw new Error("Trying to add fold to FoldRow that doesn't have a matching row");r.foldLine=this},u.prototype.containsRow=function(r){return r>=this.start.row&&r<=this.end.row},u.prototype.walk=function(r,f,l){var n=0,i=this.folds,o,s,c,p=!0;f==null&&(f=this.end.row,l=this.end.column);for(var $=0;$0)){var p=a(f,s.start);return c===0?l&&p!==0?-o-2:o:p>0||p===0&&!l?o:-o-1}}return-o-1},r.prototype.add=function(f){var l=!f.isEmpty(),n=this.pointIndex(f.start,l);n<0&&(n=-n-1);var i=this.pointIndex(f.end,l,n);return i<0?i=-i-1:i++,this.ranges.splice(n,i-n,f)},r.prototype.addList=function(f){for(var l=[],n=f.length;n--;)l.push.apply(l,this.add(f[n]));return l},r.prototype.substractPoint=function(f){var l=this.pointIndex(f);if(l>=0)return this.ranges.splice(l,1)},r.prototype.merge=function(){var f=[],l=this.ranges;l=l.sort(function(c,p){return a(c.start,p.start)});for(var n=l[0],i,o=1;o=0},r.prototype.containsPoint=function(f){return this.pointIndex(f)>=0},r.prototype.rangeAtPoint=function(f){var l=this.pointIndex(f);if(l>=0)return this.ranges[l]},r.prototype.clipRows=function(f,l){var n=this.ranges;if(n[0].start.row>l||n[n.length-1].start.row=i)break}if(f.action=="insert")for(var v=o-i,C=-l.column+n.column;ci)break;if($.start.row==i&&$.start.column>=l.column&&($.start.column==l.column&&this.$bias<=0||($.start.column+=C,$.start.row+=v)),$.end.row==i&&$.end.column>=l.column){if($.end.column==l.column&&this.$bias<0)continue;$.end.column==l.column&&C>0&&c$.start.column&&$.end.column==s[c+1].start.column&&($.end.column-=C),$.end.column+=C,$.end.row+=v}}else for(var v=i-o,C=l.column-n.column;co)break;$.end.rowl.column)&&($.end.column=l.column,$.end.row=l.row):($.end.column+=C,$.end.row+=v):$.end.row>o&&($.end.row+=v),$.start.rowl.column)&&($.start.column=l.column,$.start.row=l.row):($.start.column+=C,$.start.row+=v):$.start.row>o&&($.start.row+=v)}if(v!=0&&c=n)return c;if(c.end.row>n)return null}return null},this.getNextFoldLine=function(n,i){var o=this.$foldData,s=0;for(i&&(s=o.indexOf(i)),s==-1&&(s=0),s;s=n)return c}return null},this.getFoldedRowCount=function(n,i){for(var o=this.$foldData,s=i-n+1,c=0;c=i){v=n?s-=i-v:s=0);break}else $>=n&&(v>=n?s-=$-v:s-=$-n+1)}return s},this.$addFoldLine=function(n){return this.$foldData.push(n),this.$foldData.sort(function(i,o){return i.start.row-o.start.row}),n},this.addFold=function(n,i){var o=this.$foldData,s=!1,c;n instanceof u?c=n:(c=new u(i,n),c.collapseChildren=i.collapseChildren),this.$clipRangeToDocument(c.range);var p=c.start.row,$=c.start.column,v=c.end.row,C=c.end.column,y=this.getFoldAt(p,$,1),_=this.getFoldAt(v,C,-1);if(y&&_==y)return y.addSubFold(c);y&&!y.range.isStart(p,$)&&this.removeFold(y),_&&!_.range.isEnd(v,C)&&this.removeFold(_);var b=this.getFoldsInRange(c.range);b.length>0&&(this.removeFolds(b),c.collapseChildren||b.forEach(function(M){c.addSubFold(M)}));for(var E=0;E0&&this.foldAll(n.start.row+1,n.end.row,n.collapseChildren-1),n.subFolds=[]},this.expandFolds=function(n){n.forEach(function(i){this.expandFold(i)},this)},this.unfold=function(n,i){var o,s;if(n==null)o=new g(0,0,this.getLength(),0),i==null&&(i=!0);else if(typeof n=="number")o=new g(n,0,n,this.getLine(n).length);else if("row"in n)o=g.fromPoints(n,n);else{if(Array.isArray(n))return s=[],n.forEach(function(p){s=s.concat(this.unfold(p))},this),s;o=n}s=this.getFoldsInRangeList(o);for(var c=s;s.length==1&&g.comparePoints(s[0].start,o.start)<0&&g.comparePoints(s[0].end,o.end)>0;)this.expandFolds(s),s=this.getFoldsInRangeList(o);if(i!=!1?this.removeFolds(s):this.expandFolds(s),c.length)return c},this.isRowFolded=function(n,i){return!!this.getFoldLine(n,i)},this.getRowFoldEnd=function(n,i){var o=this.getFoldLine(n,i);return o?o.end.row:n},this.getRowFoldStart=function(n,i){var o=this.getFoldLine(n,i);return o?o.start.row:n},this.getFoldDisplayLine=function(n,i,o,s,c){s==null&&(s=n.start.row),c==null&&(c=0),i==null&&(i=n.end.row),o==null&&(o=this.getLine(i).length);var p=this.doc,$="";return n.walk(function(v,C,y,_){if(!(CC)break;while(c&&$.test(c.type)&&!/^comment.start/.test(c.type));c=s.stepBackward()}else c=s.getCurrentToken();return v.end.row=s.getCurrentTokenRow(),v.end.column=s.getCurrentTokenColumn(),/^comment.end/.test(c.type)||(v.end.column+=c.value.length-2),v}},this.foldAll=function(n,i,o,s){o==null&&(o=1e5);var c=this.foldWidgets;if(!!c){i=i||this.getLength(),n=n||0;for(var p=n;p=n&&(p=$.end.row,$.collapseChildren=o,this.addFold("...",$))}}},this.foldToLevel=function(n){for(this.foldAll();n-- >0;)this.unfold(null,!1)},this.foldAllComments=function(){var n=this;this.foldAll(null,null,null,function(i){for(var o=n.getTokens(i),s=0;s=0;){var p=o[s];if(p==null&&(p=o[s]=this.getFoldWidget(s)),p=="start"){var $=this.getFoldWidgetRange(s);if(c||(c=$),$&&$.end.row>=n)break}s--}return{range:s!==-1&&$,firstRange:c}},this.onFoldWidgetClick=function(n,i){i instanceof f&&(i=i.domEvent);var o={children:i.shiftKey,all:i.ctrlKey||i.metaKey,siblings:i.altKey},s=this.$toggleFoldWidget(n,o);if(!s){var c=i.target||i.srcElement;c&&/ace_fold-widget/.test(c.className)&&(c.className+=" ace_invalid")}},this.$toggleFoldWidget=function(n,i){if(!!this.getFoldWidget){var o=this.getFoldWidget(n),s=this.getLine(n),c=o==="end"?-1:1,p=this.getFoldAt(n,c===-1?0:s.length,c);if(p)return i.children||i.all?this.removeFold(p):this.expandFold(p),p;var $=this.getFoldWidgetRange(n,!0);if($&&!$.isMultiLine()&&(p=this.getFoldAt($.start.row,$.start.column,1),p&&$.isEqual(p.range)))return this.removeFold(p),p;if(i.siblings){var v=this.getParentFoldRangeData(n);if(v.range)var C=v.range.start.row+1,y=v.range.end.row;this.foldAll(C,y,i.all?1e4:0)}else i.children?(y=$?$.end.row:this.getLength(),this.foldAll(n+1,y,i.all?1e4:0)):$&&(i.all&&($.collapseChildren=1e4),this.addFold("...",$));return $}},this.toggleFoldWidget=function(n){var i=this.selection.getCursor().row;i=this.getRowFoldStart(i);var o=this.$toggleFoldWidget(i,{});if(!o){var s=this.getParentFoldRangeData(i,!0);if(o=s.range||s.firstRange,o){i=o.start.row;var c=this.getFoldAt(i,this.getLine(i).length,1);c?this.removeFold(c):this.addFold("...",o)}}},this.updateFoldWidgets=function(n){var i=n.start.row,o=n.end.row-i;if(o===0)this.foldWidgets[i]=null;else if(n.action=="remove")this.foldWidgets.splice(i,o+1,null);else{var s=Array(o+1);s.unshift(i,1),this.foldWidgets.splice.apply(this.foldWidgets,s)}},this.tokenizerUpdateFoldWidgets=function(n){var i=n.data;i.first!=i.last&&this.foldWidgets.length>i.first&&this.foldWidgets.splice(i.first,this.foldWidgets.length)}}h.Folding=l}),ace.define("ace/edit_session/bracket_match",["require","exports","module","ace/token_iterator","ace/range"],function(e,h,m){var g=e("../token_iterator").TokenIterator,a=e("../range").Range;function u(){this.findMatchingBracket=function(r,f){if(r.column==0)return null;var l=f||this.getLine(r.row).charAt(r.column-1);if(l=="")return null;var n=l.match(/([\(\[\{])|([\)\]\}])/);return n?n[1]?this.$findClosingBracket(n[1],r):this.$findOpeningBracket(n[2],r):null},this.getBracketRange=function(r){var f=this.getLine(r.row),l=!0,n,i=f.charAt(r.column-1),o=i&&i.match(/([\(\[\{])|([\)\]\}])/);if(o||(i=f.charAt(r.column),r={row:r.row,column:r.column+1},o=i&&i.match(/([\(\[\{])|([\)\]\}])/),l=!1),!o)return null;if(o[1]){var s=this.$findClosingBracket(o[1],r);if(!s)return null;n=a.fromPoints(r,s),l||(n.end.column++,n.start.column--),n.cursor=n.end}else{var s=this.$findOpeningBracket(o[2],r);if(!s)return null;n=a.fromPoints(s,r),l||(n.start.column++,n.end.column--),n.cursor=n.start}return n},this.getMatchingBracketRanges=function(r,f){var l=this.getLine(r.row),n=/([\(\[\{])|([\)\]\}])/,i=!f&&l.charAt(r.column-1),o=i&&i.match(n);if(o||(i=(f===void 0||f)&&l.charAt(r.column),r={row:r.row,column:r.column+1},o=i&&i.match(n)),!o)return null;var s=new a(r.row,r.column-1,r.row,r.column),c=o[1]?this.$findClosingBracket(o[1],r):this.$findOpeningBracket(o[2],r);if(!c)return[s];var p=new a(c.row,c.column,c.row,c.column+1);return[s,p]},this.$brackets={")":"(","(":")","]":"[","[":"]","{":"}","}":"{","<":">",">":"<"},this.$findOpeningBracket=function(r,f,l){var n=this.$brackets[r],i=1,o=new g(this,f.row,f.column),s=o.getCurrentToken();if(s||(s=o.stepForward()),!!s){l||(l=new RegExp("(\\.?"+s.type.replace(".","\\.").replace("rparen",".paren").replace(/\b(?:end)\b/,"(?:start|begin|end)").replace(/-close\b/,"-(close|open)")+")+"));for(var c=f.column-o.getCurrentTokenColumn()-2,p=s.value;;){for(;c>=0;){var $=p.charAt(c);if($==n){if(i-=1,i==0)return{row:o.getCurrentTokenRow(),column:c+o.getCurrentTokenColumn()}}else $==r&&(i+=1);c-=1}do s=o.stepBackward();while(s&&!l.test(s.type));if(s==null)break;p=s.value,c=p.length-1}return null}},this.$findClosingBracket=function(r,f,l){var n=this.$brackets[r],i=1,o=new g(this,f.row,f.column),s=o.getCurrentToken();if(s||(s=o.stepForward()),!!s){l||(l=new RegExp("(\\.?"+s.type.replace(".","\\.").replace("lparen",".paren").replace(/\b(?:start|begin)\b/,"(?:start|begin|end)").replace(/-open\b/,"-(close|open)")+")+"));for(var c=f.column-o.getCurrentTokenColumn();;){for(var p=s.value,$=p.length;c<$;){var v=p.charAt(c);if(v==n){if(i-=1,i==0)return{row:o.getCurrentTokenRow(),column:c+o.getCurrentTokenColumn()}}else v==r&&(i+=1);c+=1}do s=o.stepForward();while(s&&!l.test(s.type));if(s==null)break;c=0}return null}},this.getMatchingTags=function(r){var f=new g(this,r.row,r.column),l=this.$findTagName(f);if(!!l){var n=f.stepBackward();return n.value==="<"?this.$findClosingTag(f,l):this.$findOpeningTag(f,l)}},this.$findTagName=function(r){var f=r.getCurrentToken(),l=!1,n=!1;if(f&&f.type.indexOf("tag-name")===-1)do n?f=r.stepBackward():f=r.stepForward(),f&&(f.value==="/>"?n=!0:f.type.indexOf("tag-name")!==-1&&(l=!0));while(f&&!l);return f},this.$findClosingTag=function(r,f){var l,n=f.value,i=f.value,o=0,s=new a(r.getCurrentTokenRow(),r.getCurrentTokenColumn(),r.getCurrentTokenRow(),r.getCurrentTokenColumn()+1);f=r.stepForward();var c=new a(r.getCurrentTokenRow(),r.getCurrentTokenColumn(),r.getCurrentTokenRow(),r.getCurrentTokenColumn()+f.value.length),p=!1;do if(l=f,f=r.stepForward(),f){if(f.value===">"&&!p){var $=new a(r.getCurrentTokenRow(),r.getCurrentTokenColumn(),r.getCurrentTokenRow(),r.getCurrentTokenColumn()+1);p=!0}if(f.type.indexOf("tag-name")!==-1){if(n=f.value,i===n){if(l.value==="<")o++;else if(l.value==="")var y=new a(r.getCurrentTokenRow(),r.getCurrentTokenColumn(),r.getCurrentTokenRow(),r.getCurrentTokenColumn()+1);else return}}}else if(i===n&&f.value==="/>"&&(o--,o<0))var v=new a(r.getCurrentTokenRow(),r.getCurrentTokenColumn(),r.getCurrentTokenRow(),r.getCurrentTokenColumn()+2),C=v,y=C,$=new a(c.end.row,c.end.column,c.end.row,c.end.column+1)}while(f&&o>=0);if(s&&$&&v&&y&&c&&C)return{openTag:new a(s.start.row,s.start.column,$.end.row,$.end.column),closeTag:new a(v.start.row,v.start.column,y.end.row,y.end.column),openTagName:c,closeTagName:C}},this.$findOpeningTag=function(r,f){var l=r.getCurrentToken(),n=f.value,i=0,o=r.getCurrentTokenRow(),s=r.getCurrentTokenColumn(),c=s+2,p=new a(o,s,o,c);r.stepForward();var $=new a(r.getCurrentTokenRow(),r.getCurrentTokenColumn(),r.getCurrentTokenRow(),r.getCurrentTokenColumn()+f.value.length);if(f=r.stepForward(),!(!f||f.value!==">")){var v=new a(r.getCurrentTokenRow(),r.getCurrentTokenColumn(),r.getCurrentTokenRow(),r.getCurrentTokenColumn()+1);r.stepBackward(),r.stepBackward();do if(f=l,o=r.getCurrentTokenRow(),s=r.getCurrentTokenColumn(),c=s+f.value.length,l=r.stepBackward(),f){if(f.type.indexOf("tag-name")!==-1){if(n===f.value)if(l.value==="<"){if(i++,i>0){var C=new a(o,s,o,c),y=new a(r.getCurrentTokenRow(),r.getCurrentTokenColumn(),r.getCurrentTokenRow(),r.getCurrentTokenColumn()+1);do f=r.stepForward();while(f&&f.value!==">");var _=new a(r.getCurrentTokenRow(),r.getCurrentTokenColumn(),r.getCurrentTokenRow(),r.getCurrentTokenColumn()+1)}}else l.value===""){for(var b=0,E=l;E;){if(E.type.indexOf("tag-name")!==-1&&E.value===n){i--;break}else if(E.value==="<")break;E=r.stepBackward(),b++}for(var x=0;xw&&(this.$docRowCache.splice(w,S),this.$screenRowCache.splice(w,S))},k.prototype.$getRowCacheIndex=function(T,S){for(var w=0,L=T.length-1;w<=L;){var q=w+L>>1,A=T[q];if(S>A)w=q+1;else if(S=S));A++);return L=w[A],L?(L.index=A,L.start=q-L.value.length,L):null},k.prototype.setUndoManager=function(T){if(this.$undoManager=T,this.$informUndoManager&&this.$informUndoManager.cancel(),T){var S=this;T.addSession(this),this.$syncInformUndoManager=function(){S.$informUndoManager.cancel(),S.mergeUndoDeltas=!1},this.$informUndoManager=a.delayedCall(this.$syncInformUndoManager)}else this.$syncInformUndoManager=function(){}},k.prototype.markUndoGroup=function(){this.$syncInformUndoManager&&this.$syncInformUndoManager()},k.prototype.getUndoManager=function(){return this.$undoManager||this.$defaultUndoManager},k.prototype.getTabString=function(){return this.getUseSoftTabs()?a.stringRepeat(" ",this.getTabSize()):" "},k.prototype.setUseSoftTabs=function(T){this.setOption("useSoftTabs",T)},k.prototype.getUseSoftTabs=function(){return this.$useSoftTabs&&!this.$mode.$indentWithTabs},k.prototype.setTabSize=function(T){this.setOption("tabSize",T)},k.prototype.getTabSize=function(){return this.$tabSize},k.prototype.isTabStop=function(T){return this.$useSoftTabs&&T.column%this.$tabSize==0},k.prototype.setNavigateWithinSoftTabs=function(T){this.setOption("navigateWithinSoftTabs",T)},k.prototype.getNavigateWithinSoftTabs=function(){return this.$navigateWithinSoftTabs},k.prototype.setOverwrite=function(T){this.setOption("overwrite",T)},k.prototype.getOverwrite=function(){return this.$overwrite},k.prototype.toggleOverwrite=function(){this.setOverwrite(!this.$overwrite)},k.prototype.addGutterDecoration=function(T,S){this.$decorations[T]||(this.$decorations[T]=""),this.$decorations[T]+=" "+S,this._signal("changeBreakpoint",{})},k.prototype.removeGutterDecoration=function(T,S){this.$decorations[T]=(this.$decorations[T]||"").replace(" "+S,""),this._signal("changeBreakpoint",{})},k.prototype.getBreakpoints=function(){return this.$breakpoints},k.prototype.setBreakpoints=function(T){this.$breakpoints=[];for(var S=0;S0&&(L=!!w.charAt(S-1).match(this.tokenRe)),L||(L=!!w.charAt(S).match(this.tokenRe)),L)var q=this.tokenRe;else if(/^\s+$/.test(w.slice(S-1,S+1)))var q=/\s/;else var q=this.nonTokenRe;var A=S;if(A>0){do A--;while(A>=0&&w.charAt(A).match(q));A++}for(var I=S;IT&&(T=S.screenWidth)}),this.lineWidgetWidth=T},k.prototype.$computeWidth=function(T){if(this.$modified||T){if(this.$modified=!1,this.$useWrapMode)return this.screenWidth=this.$wrapLimit;for(var S=this.doc.getAllLines(),w=this.$rowLengthCache,L=0,q=0,A=this.$foldData[q],I=A?A.start.row:1/0,F=S.length,V=0;VI){if(V=A.end.row+1,V>=F)break;A=this.$foldData[q++],I=A?A.start.row:1/0}w[V]==null&&(w[V]=this.$getStringScreenWidth(S[V])[0]),w[V]>L&&(L=w[V])}this.screenWidth=L}},k.prototype.getLine=function(T){return this.doc.getLine(T)},k.prototype.getLines=function(T,S){return this.doc.getLines(T,S)},k.prototype.getLength=function(){return this.doc.getLength()},k.prototype.getTextRange=function(T){return this.doc.getTextRange(T||this.selection.getRange())},k.prototype.insert=function(T,S){return this.doc.insert(T,S)},k.prototype.remove=function(T){return this.doc.remove(T)},k.prototype.removeFullLines=function(T,S){return this.doc.removeFullLines(T,S)},k.prototype.undoChanges=function(T,S){if(!!T.length){this.$fromUndo=!0;for(var w=T.length-1;w!=-1;w--){var L=T[w];L.action=="insert"||L.action=="remove"?this.doc.revertDelta(L):L.folds&&this.addFolds(L.folds)}!S&&this.$undoSelect&&(T.selectionBefore?this.selection.fromJSON(T.selectionBefore):this.selection.setRange(this.$getUndoSelection(T,!0))),this.$fromUndo=!1}},k.prototype.redoChanges=function(T,S){if(!!T.length){this.$fromUndo=!0;for(var w=0;wT.end.column&&(A.start.column+=F),A.end.row==T.end.row&&A.end.column>T.end.column&&(A.end.column+=F)),I&&A.start.row>=T.end.row&&(A.start.row+=I,A.end.row+=I)}if(A.end=this.insert(A.start,L),q.length){var V=T.start,R=A.start,I=R.row-V.row,F=R.column-V.column;this.addFolds(q.map(function(P){return P=P.clone(),P.start.row==V.row&&(P.start.column+=F),P.end.row==V.row&&(P.end.column+=F),P.start.row+=I,P.end.row+=I,P}))}return A},k.prototype.indentRows=function(T,S,w){w=w.replace(/\t/g,this.getTabString());for(var L=T;L<=S;L++)this.doc.insertInLine({row:L,column:0},w)},k.prototype.outdentRows=function(T){for(var S=T.collapseRows(),w=new i(0,0,0,0),L=this.getTabSize(),q=S.start.row;q<=S.end.row;++q){var A=this.getLine(q);w.start.row=q,w.end.row=q;for(var I=0;I0){var L=this.getRowFoldEnd(S+w);if(L>this.doc.getLength()-1)return 0;var q=L-S}else{T=this.$clipRowToDocument(T),S=this.$clipRowToDocument(S);var q=S-T+1}var A=new i(T,0,S,Number.MAX_VALUE),I=this.getFoldsInRange(A).map(function(V){return V=V.clone(),V.start.row+=q,V.end.row+=q,V}),F=w==0?this.doc.getLines(T,S):this.doc.removeFullLines(T,S);return this.doc.insertFullLines(T+q,F),I.length&&this.addFolds(I),q},k.prototype.moveLinesUp=function(T,S){return this.$moveLines(T,S,-1)},k.prototype.moveLinesDown=function(T,S){return this.$moveLines(T,S,1)},k.prototype.duplicateLines=function(T,S){return this.$moveLines(T,S,0)},k.prototype.$clipRowToDocument=function(T){return Math.max(0,Math.min(T,this.doc.getLength()-1))},k.prototype.$clipColumnToRow=function(T,S){return S<0?0:Math.min(this.doc.getLine(T).length,S)},k.prototype.$clipPositionToDocument=function(T,S){if(S=Math.max(0,S),T<0)T=0,S=0;else{var w=this.doc.getLength();T>=w?(T=w-1,S=this.doc.getLine(w-1).length):S=Math.min(this.doc.getLine(T).length,S)}return{row:T,column:S}},k.prototype.$clipRangeToDocument=function(T){T.start.row<0?(T.start.row=0,T.start.column=0):T.start.column=this.$clipColumnToRow(T.start.row,T.start.column);var S=this.doc.getLength()-1;return T.end.row>S?(T.end.row=S,T.end.column=this.doc.getLine(S).length):T.end.column=this.$clipColumnToRow(T.end.row,T.end.column),T},k.prototype.setUseWrapMode=function(T){if(T!=this.$useWrapMode){if(this.$useWrapMode=T,this.$modified=!0,this.$resetRowCache(0),T){var S=this.getLength();this.$wrapData=Array(S),this.$updateWrapData(0,S-1)}this._signal("changeWrapMode")}},k.prototype.getUseWrapMode=function(){return this.$useWrapMode},k.prototype.setWrapLimitRange=function(T,S){(this.$wrapLimitRange.min!==T||this.$wrapLimitRange.max!==S)&&(this.$wrapLimitRange={min:T,max:S},this.$modified=!0,this.$bidiHandler.markAsDirty(),this.$useWrapMode&&this._signal("changeWrapMode"))},k.prototype.adjustWrapLimit=function(T,S){var w=this.$wrapLimitRange;w.max<0&&(w={min:S,max:S});var L=this.$constrainWrapLimit(T,w.min,w.max);return L!=this.$wrapLimit&&L>1?(this.$wrapLimit=L,this.$modified=!0,this.$useWrapMode&&(this.$updateWrapData(0,this.getLength()-1),this.$resetRowCache(0),this._signal("changeWrapLimit")),!0):!1},k.prototype.$constrainWrapLimit=function(T,S,w){return S&&(T=Math.max(S,T)),w&&(T=Math.min(w,T)),T},k.prototype.getWrapLimit=function(){return this.$wrapLimit},k.prototype.setWrapLimit=function(T){this.setWrapLimitRange(T,T)},k.prototype.getWrapLimitRange=function(){return{min:this.$wrapLimitRange.min,max:this.$wrapLimitRange.max}},k.prototype.$updateInternalDataOnChange=function(T){var S=this.$useWrapMode,w=T.action,L=T.start,q=T.end,A=L.row,I=q.row,F=I-A,V=null;if(this.$updating=!0,F!=0)if(w==="remove"){this[S?"$wrapData":"$rowLengthCache"].splice(A,F);var R=this.$foldData;V=this.getFoldsInRange(T),this.removeFolds(V);var B=this.getFoldLine(q.row),N=0;if(B){B.addRemoveChars(q.row,q.column,L.column-q.column),B.shiftRow(-F);var P=this.getFoldLine(A);P&&P!==B&&(P.merge(B),B=P),N=R.indexOf(B)+1}for(N;N=q.row&&B.shiftRow(-F)}I=A}else{var j=Array(F);j.unshift(A,0);var D=S?this.$wrapData:this.$rowLengthCache;D.splice.apply(D,j);var R=this.$foldData,B=this.getFoldLine(A),N=0;if(B){var W=B.range.compareInside(L.row,L.column);W==0?(B=B.split(L.row,L.column),B&&(B.shiftRow(F),B.addRemoveChars(I,0,q.column-L.column))):W==-1&&(B.addRemoveChars(A,0,q.column-L.column),B.shiftRow(F)),N=R.indexOf(B)+1}for(N;N=A&&B.shiftRow(F)}}else{F=Math.abs(T.start.column-T.end.column),w==="remove"&&(V=this.getFoldsInRange(T),this.removeFolds(V),F=-F);var B=this.getFoldLine(A);B&&B.addRemoveChars(A,L.column,F)}return S&&this.$wrapData.length!=this.doc.getLength()&&console.error("doc.getLength() and $wrapData.length have to be the same!"),this.$updating=!1,S?this.$updateWrapData(A,I):this.$updateRowLengthCache(A,I),V},k.prototype.$updateRowLengthCache=function(T,S){this.$rowLengthCache[T]=null,this.$rowLengthCache[S]=null},k.prototype.$updateWrapData=function(T,S){var w=this.doc.getAllLines(),L=this.getTabSize(),q=this.$wrapData,A=this.$wrapLimit,I,F,V=T;for(S=Math.min(S,w.length-1);V<=S;)F=this.getFoldLine(V,F),F?(I=[],F.walk(function(R,B,N,P){var j;if(R!=null){j=this.$getDisplayTokens(R,I.length),j[0]=y;for(var D=1;DS-P;){var j=A+S-P;if(T[j-1]>=E&&T[j]>=E){N(j);continue}if(T[j]==y||T[j]==_){for(j;j!=A-1&&T[j]!=y;j--);if(j>A){N(j);continue}for(j=A+S,j;j>2)),A-1);j>D&&T[j]D&&T[j]D&&T[j]==b;)j--}else for(;j>D&&T[j]D){N(++j);continue}j=A+S,T[j]==C&&j--,N(j-P)}return L},k.prototype.$getDisplayTokens=function(T,S){var w=[],L;S=S||0;for(var q=0;q39&&A<48||A>57&&A<64?w.push(b):A>=4352&&M(A)?w.push(v,C):w.push(v)}return w},k.prototype.$getStringScreenWidth=function(T,S,w){if(S==0)return[0,0];S==null&&(S=1/0),w=w||0;var L,q;for(q=0;q=4352&&M(L)?w+=2:w+=1,!(w>S));q++);return[w,q]},k.prototype.getRowLength=function(T){var S=1;return this.lineWidgets&&(S+=this.lineWidgets[T]&&this.lineWidgets[T].rowCount||0),!this.$useWrapMode||!this.$wrapData[T]?S:this.$wrapData[T].length+S},k.prototype.getRowLineCount=function(T){return!this.$useWrapMode||!this.$wrapData[T]?1:this.$wrapData[T].length+1},k.prototype.getRowWrapIndent=function(T){if(this.$useWrapMode){var S=this.screenToDocumentPosition(T,Number.MAX_VALUE),w=this.$wrapData[S.row];return w.length&&w[0]=0)var F=R[B],q=this.$docRowCache[B],P=T>R[N-1];else var P=!N;for(var j=this.getLength()-1,D=this.getNextFoldLine(q),W=D?D.start.row:1/0;F<=T&&(V=this.getRowLength(q),!(F+V>T||q>=j));)F+=V,q++,q>W&&(q=D.end.row+1,D=this.getNextFoldLine(q,D),W=D?D.start.row:1/0),P&&(this.$docRowCache.push(q),this.$screenRowCache.push(F));if(D&&D.start.row<=q)L=this.getFoldDisplayLine(D),q=D.start.row;else{if(F+V<=T||q>j)return{row:j,column:this.getLine(j).length};L=this.getLine(q),D=null}var H=0,z=Math.floor(T-F);if(this.$useWrapMode){var K=this.$wrapData[q];K&&(I=K[z],z>0&&K.length&&(H=K.indent,A=K[z-1]||K[K.length-1],L=L.substring(A)))}return w!==void 0&&this.$bidiHandler.isBidiRow(F+z,q,z)&&(S=this.$bidiHandler.offsetToCol(w)),A+=this.$getStringScreenWidth(L,S-H)[1],this.$useWrapMode&&A>=I&&(A=I-1),D?D.idxToPosition(A):{row:q,column:A}},k.prototype.documentToScreenPosition=function(T,S){if(typeof S=="undefined")var w=this.$clipPositionToDocument(T.row,T.column);else w=this.$clipPositionToDocument(T,S);T=w.row,S=w.column;var L=0,q=null,A=null;A=this.getFoldAt(T,S,1),A&&(T=A.start.row,S=A.start.column);var I,F=0,V=this.$docRowCache,R=this.$getRowCacheIndex(V,T),B=V.length;if(B&&R>=0)var F=V[R],L=this.$screenRowCache[R],N=T>V[B-1];else var N=!B;for(var P=this.getNextFoldLine(F),j=P?P.start.row:1/0;F=j){if(I=P.end.row+1,I>T)break;P=this.getNextFoldLine(I,P),j=P?P.start.row:1/0}else I=F+1;L+=this.getRowLength(F),F=I,N&&(this.$docRowCache.push(F),this.$screenRowCache.push(L))}var D="";P&&F>=j?(D=this.getFoldDisplayLine(P,T,S),q=P.start.row):(D=this.getLine(T).substring(0,S),q=T);var W=0;if(this.$useWrapMode){var H=this.$wrapData[q];if(H){for(var z=0;D.length>=H[z];)L++,z++;D=D.substring(H[z-1]||0,D.length),W=z>0?H.indent:0}}return this.lineWidgets&&this.lineWidgets[F]&&this.lineWidgets[F].rowsAbove&&(L+=this.lineWidgets[F].rowsAbove),{row:L,column:W+this.$getStringScreenWidth(D)[0]}},k.prototype.documentToScreenColumn=function(T,S){return this.documentToScreenPosition(T,S).column},k.prototype.documentToScreenRow=function(T,S){return this.documentToScreenPosition(T,S).row},k.prototype.getScreenLength=function(){var T=0,S=null;if(this.$useWrapMode)for(var q=this.$wrapData.length,A=0,L=0,S=this.$foldData[L++],I=S?S.start.row:1/0;AI&&(A=S.end.row+1,S=this.$foldData[L++],I=S?S.start.row:1/0)}else{T=this.getLength();for(var w=this.$foldData,L=0;Lw));A++);return[L,A]})},k.prototype.destroy=function(){this.destroyed||(this.bgTokenizer.setDocument(null),this.bgTokenizer.cleanup(),this.destroyed=!0),this.$stopWorker(),this.removeAllListeners(),this.doc&&this.doc.off("change",this.$onChange),this.selection.detach()},k}();$.$uid=0,$.prototype.$modes=r.$modes,$.prototype.getValue=$.prototype.toString,$.prototype.$defaultUndoManager={undo:function(){},redo:function(){},hasUndo:function(){},hasRedo:function(){},reset:function(){},add:function(){},addSelection:function(){},startNewGroup:function(){},addSession:function(){}},$.prototype.$overwrite=!1,$.prototype.$mode=null,$.prototype.$modeId=null,$.prototype.$scrollTop=0,$.prototype.$scrollLeft=0,$.prototype.$wrapLimit=80,$.prototype.$useWrapMode=!1,$.prototype.$wrapLimitRange={min:null,max:null},$.prototype.lineWidgets=null,$.prototype.isFullWidth=M,g.implement($.prototype,f);var v=1,C=2,y=3,_=4,b=9,E=10,x=11,O=12;function M(k){return k<4352?!1:k>=4352&&k<=4447||k>=4515&&k<=4519||k>=4602&&k<=4607||k>=9001&&k<=9002||k>=11904&&k<=11929||k>=11931&&k<=12019||k>=12032&&k<=12245||k>=12272&&k<=12283||k>=12288&&k<=12350||k>=12353&&k<=12438||k>=12441&&k<=12543||k>=12549&&k<=12589||k>=12593&&k<=12686||k>=12688&&k<=12730||k>=12736&&k<=12771||k>=12784&&k<=12830||k>=12832&&k<=12871||k>=12880&&k<=13054||k>=13056&&k<=19903||k>=19968&&k<=42124||k>=42128&&k<=42182||k>=43360&&k<=43388||k>=44032&&k<=55203||k>=55216&&k<=55238||k>=55243&&k<=55291||k>=63744&&k<=64255||k>=65040&&k<=65049||k>=65072&&k<=65106||k>=65108&&k<=65126||k>=65128&&k<=65131||k>=65281&&k<=65376||k>=65504&&k<=65510}e("./edit_session/folding").Folding.call($.prototype),e("./edit_session/bracket_match").BracketMatch.call($.prototype),r.defineOptions($.prototype,"session",{wrap:{set:function(k){if(!k||k=="off"?k=!1:k=="free"?k=!0:k=="printMargin"?k=-1:typeof k=="string"&&(k=parseInt(k,10)||!1),this.$wrap!=k)if(this.$wrap=k,!k)this.setUseWrapMode(!1);else{var T=typeof k=="number"?k:null;this.setWrapLimitRange(T,T),this.setUseWrapMode(!0)}},get:function(){return this.getUseWrapMode()?this.$wrap==-1?"printMargin":this.getWrapLimitRange().min?this.$wrap:"free":"off"},handlesSet:!0},wrapMethod:{set:function(k){k=k=="auto"?this.$mode.type!="text":k!="text",k!=this.$wrapAsCode&&(this.$wrapAsCode=k,this.$useWrapMode&&(this.$useWrapMode=!1,this.setUseWrapMode(!0)))},initialValue:"auto"},indentedSoftWrap:{set:function(){this.$useWrapMode&&(this.$useWrapMode=!1,this.setUseWrapMode(!0))},initialValue:!0},firstLineNumber:{set:function(){this._signal("changeBreakpoint")},initialValue:1},useWorker:{set:function(k){this.$useWorker=k,this.$stopWorker(),k&&this.$startWorker()},initialValue:!0},useSoftTabs:{initialValue:!0},tabSize:{set:function(k){k=parseInt(k),k>0&&this.$tabSize!==k&&(this.$modified=!0,this.$rowLengthCache=[],this.$tabSize=k,this._signal("changeTabSize"))},initialValue:4,handlesSet:!0},navigateWithinSoftTabs:{initialValue:!1},foldStyle:{set:function(k){this.setFoldStyle(k)},handlesSet:!0},overwrite:{set:function(k){this._signal("changeOverwrite")},initialValue:!1},newLineMode:{set:function(k){this.doc.setNewLineMode(k)},get:function(){return this.doc.getNewLineMode()},handlesSet:!0},mode:{set:function(k){this.setMode(k)},get:function(){return this.$modeId},handlesSet:!0}}),h.EditSession=$}),ace.define("ace/search",["require","exports","module","ace/lib/lang","ace/lib/oop","ace/range"],function(e,h,m){var g=e("./lib/lang"),a=e("./lib/oop"),u=e("./range").Range,r=function(){function l(){this.$options={}}return l.prototype.set=function(n){return a.mixin(this.$options,n),this},l.prototype.getOptions=function(){return g.copyObject(this.$options)},l.prototype.setOptions=function(n){this.$options=n},l.prototype.find=function(n){var i=this.$options,o=this.$matchIterator(n,i);if(!o)return!1;var s=null;return o.forEach(function(c,p,$,v){return s=new u(c,p,$,v),p==v&&i.start&&i.start.start&&i.skipCurrent!=!1&&s.isEqual(i.start)?(s=null,!1):!0}),s},l.prototype.findAll=function(n){var i=this.$options;if(!i.needle)return[];this.$assembleRegExp(i);var o=i.range,s=o?n.getLines(o.start.row,o.end.row):n.doc.getAllLines(),c=[],p=i.re;if(i.$isMultiLine){var $=p.length,v=s.length-$,C;e:for(var y=p.offset||0;y<=v;y++){for(var _=0;_<$;_++)if(s[y+_].search(p[_])==-1)continue e;var b=s[y],E=s[y+$-1],x=b.length-b.match(p[0])[0].length,O=E.match(p[$-1])[0].length;C&&C.end.row===y&&C.end.column>x||(c.push(C=new u(y,x,y+$-1,O)),$>2&&(y=y+$-2))}}else for(var M=0;Mw&&c[_].end.row==L;)_--;for(c=c.slice(M,_+1),M=0,_=c.length;M<_;M++)c[M].start.row+=o.start.row,c[M].end.row+=o.start.row}return c},l.prototype.replace=function(n,i){var o=this.$options,s=this.$assembleRegExp(o);if(o.$isMultiLine)return i;if(!!s){var c=s.exec(n);if(!c||c[0].length!=n.length)return null;if(i=n.replace(s,i),o.preserveCase){i=i.split("");for(var p=Math.min(n.length,n.length);p--;){var $=n[p];$&&$.toLowerCase()!=$?i[p]=i[p].toUpperCase():i[p]=i[p].toLowerCase()}i=i.join("")}return i}},l.prototype.$assembleRegExp=function(n,i){if(n.needle instanceof RegExp)return n.re=n.needle;var o=n.needle;if(!n.needle)return n.re=!1;n.regExp||(o=g.escapeRegExp(o));var s=n.caseSensitive?"gm":"gmi";try{new RegExp(o,"u"),n.$supportsUnicodeFlag=!0,s+="u"}catch{n.$supportsUnicodeFlag=!1}if(n.wholeWord&&(o=f(o,n)),n.$isMultiLine=!i&&/[\n\r]/.test(o),n.$isMultiLine)return n.re=this.$assembleMultilineRegExp(o,s);try{var c=new RegExp(o,s)}catch{c=!1}return n.re=c},l.prototype.$assembleMultilineRegExp=function(n,i){for(var o=n.replace(/\r\n|\r|\n/g,`$ +^`).split(` +`),s=[],c=0;c=C;O--)if(E(O,Number.MAX_VALUE,x))return;if(i.wrap!=!1){for(O=y,C=v.row;O>=C;O--)if(E(O,Number.MAX_VALUE,x))return}}};else var _=function(O){var M=v.row;if(!E(M,v.column,O)){for(M=M+1;M<=y;M++)if(E(M,0,O))return;if(i.wrap!=!1){for(M=C,y=v.row;M<=y;M++)if(E(M,0,O))return}}};if(i.$isMultiLine)var b=o.length,E=function(x,O,M){var k=s?x-b+1:x;if(!(k<0||k+b>n.getLength())){var T=n.getLine(k),S=T.search(o[0]);if(!(!s&&SO)&&M(k,S,k+b-1,L))return!0}}};else if(s)var E=function(O,M,k){var T=n.getLine(O),S=[],w,L=0;for(o.lastIndex=0;w=o.exec(T);){var q=w[0].length;if(L=w.index,!q){if(L>=T.length)break;o.lastIndex=L+=g.skipEmptyMatch(T,L,p)}if(w.index+q>M)break;S.push(w.index,q)}for(var A=S.length-1;A>=0;A-=2){var I=S[A-1],q=S[A];if(k(O,I,O,I+q))return!0}};else var E=function(O,M,k){var T=n.getLine(O),S,w;for(o.lastIndex=M;w=o.exec(T);){var L=w[0].length;if(S=w.index,k(O,S,O,S+L))return!0;if(!L&&(o.lastIndex=S+=g.skipEmptyMatch(T,S,p),S>=T.length))return!1}};return{forEach:_}},l}();function f(l,n){var i=g.supportsLookbehind();function o($,v){v===void 0&&(v=!0);var C=i&&n.$supportsUnicodeFlag?new RegExp("[\\p{L}\\p{N}_]","u"):new RegExp("\\w");return C.test($)||n.regExp?i&&n.$supportsUnicodeFlag?v?"(?<=^|[^\\p{L}\\p{N}_])":"(?=[^\\p{L}\\p{N}_]|$)":"\\b":""}var s=Array.from(l),c=s[0],p=s[s.length-1];return o(c)+l+o(p,!1)}h.Search=r}),ace.define("ace/keyboard/hash_handler",["require","exports","module","ace/lib/keys","ace/lib/useragent"],function(e,h,m){var g=this&&this.__extends||function(){var i=function(o,s){return i=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(c,p){c.__proto__=p}||function(c,p){for(var $ in p)Object.prototype.hasOwnProperty.call(p,$)&&(c[$]=p[$])},i(o,s)};return function(o,s){if(typeof s!="function"&&s!==null)throw new TypeError("Class extends value "+String(s)+" is not a constructor or null");i(o,s);function c(){this.constructor=o}o.prototype=s===null?Object.create(s):(c.prototype=s.prototype,new c)}}(),a=e("../lib/keys"),u=e("../lib/useragent"),r=a.KEY_MODS,f=function(){function i(o,s){this.$init(o,s,!1)}return i.prototype.$init=function(o,s,c){this.platform=s||(u.isMac?"mac":"win"),this.commands={},this.commandKeyBinding={},this.addCommands(o),this.$singleCommand=c},i.prototype.addCommand=function(o){this.commands[o.name]&&this.removeCommand(o),this.commands[o.name]=o,o.bindKey&&this._buildKeyHash(o)},i.prototype.removeCommand=function(o,s){var c=o&&(typeof o=="string"?o:o.name);o=this.commands[c],s||delete this.commands[c];var p=this.commandKeyBinding;for(var $ in p){var v=p[$];if(v==o)delete p[$];else if(Array.isArray(v)){var C=v.indexOf(o);C!=-1&&(v.splice(C,1),v.length==1&&(p[$]=v[0]))}}},i.prototype.bindKey=function(o,s,c){if(typeof o=="object"&&o&&(c==null&&(c=o.position),o=o[this.platform]),!!o){if(typeof s=="function")return this.addCommand({exec:s,bindKey:o,name:s.name||o});o.split("|").forEach(function(p){var $="";if(p.indexOf(" ")!=-1){var v=p.split(/\s+/);p=v.pop(),v.forEach(function(_){var b=this.parseKeys(_),E=r[b.hashId]+b.key;$+=($?" ":"")+E,this._addCommandToBinding($,"chainKeys")},this),$+=" "}var C=this.parseKeys(p),y=r[C.hashId]+C.key;this._addCommandToBinding($+y,s,c)},this)}},i.prototype._addCommandToBinding=function(o,s,c){var p=this.commandKeyBinding,$;if(!s)delete p[o];else if(!p[o]||this.$singleCommand)p[o]=s;else{Array.isArray(p[o])?($=p[o].indexOf(s))!=-1&&p[o].splice($,1):p[o]=[p[o]],typeof c!="number"&&(c=l(s));var v=p[o];for($=0;$c)break}v.splice($,0,s)}},i.prototype.addCommands=function(o){o&&Object.keys(o).forEach(function(s){var c=o[s];if(!!c){if(typeof c=="string")return this.bindKey(c,s);typeof c=="function"&&(c={exec:c}),typeof c=="object"&&(c.name||(c.name=s),this.addCommand(c))}},this)},i.prototype.removeCommands=function(o){Object.keys(o).forEach(function(s){this.removeCommand(o[s])},this)},i.prototype.bindKeys=function(o){Object.keys(o).forEach(function(s){this.bindKey(s,o[s])},this)},i.prototype._buildKeyHash=function(o){this.bindKey(o.bindKey,o)},i.prototype.parseKeys=function(o){var s=o.toLowerCase().split(/[\-\+]([\-\+])?/).filter(function(y){return y}),c=s.pop(),p=a[c];if(a.FUNCTION_KEYS[p])c=a.FUNCTION_KEYS[p].toLowerCase();else if(s.length){if(s.length==1&&s[0]=="shift")return{key:c.toUpperCase(),hashId:-1}}else return{key:c,hashId:-1};for(var $=0,v=s.length;v--;){var C=a.KEY_MODS[s[v]];if(C==null)return typeof console!="undefined"&&console.error("invalid modifier "+s[v]+" in "+o),!1;$|=C}return{key:c,hashId:$}},i.prototype.findKeyCommand=function(o,s){var c=r[o]+s;return this.commandKeyBinding[c]},i.prototype.handleKeyboard=function(o,s,c,p){if(!(p<0)){var $=r[s]+c,v=this.commandKeyBinding[$];return o.$keyChain&&(o.$keyChain+=" "+$,v=this.commandKeyBinding[o.$keyChain]||v),v&&(v=="chainKeys"||v[v.length-1]=="chainKeys")?(o.$keyChain=o.$keyChain||$,{command:"null"}):(o.$keyChain&&((!s||s==4)&&c.length==1?o.$keyChain=o.$keyChain.slice(0,-$.length-1):(s==-1||p>0)&&(o.$keyChain="")),{command:v})}},i.prototype.getStatusText=function(o,s){return s.$keyChain||""},i}();function l(i){return typeof i=="object"&&i.bindKey&&i.bindKey.position||(i.isDefault?-100:0)}var n=function(i){g(o,i);function o(s,c){var p=i.call(this,s,c)||this;return p.$singleCommand=!0,p}return o}(f);n.call=function(i,o,s){f.prototype.$init.call(i,o,s,!0)},f.call=function(i,o,s){f.prototype.$init.call(i,o,s,!1)},h.HashHandler=n,h.MultiHashHandler=f}),ace.define("ace/commands/command_manager",["require","exports","module","ace/lib/oop","ace/keyboard/hash_handler","ace/lib/event_emitter"],function(e,h,m){var g=this&&this.__extends||function(){var l=function(n,i){return l=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(o,s){o.__proto__=s}||function(o,s){for(var c in s)Object.prototype.hasOwnProperty.call(s,c)&&(o[c]=s[c])},l(n,i)};return function(n,i){if(typeof i!="function"&&i!==null)throw new TypeError("Class extends value "+String(i)+" is not a constructor or null");l(n,i);function o(){this.constructor=n}n.prototype=i===null?Object.create(i):(o.prototype=i.prototype,new o)}}(),a=e("../lib/oop"),u=e("../keyboard/hash_handler").MultiHashHandler,r=e("../lib/event_emitter").EventEmitter,f=function(l){g(n,l);function n(i,o){var s=l.call(this,o,i)||this;return s.byName=s.commands,s.setDefaultHandler("exec",function(c){return c.args?c.command.exec(c.editor,c.args,c.event,!1):c.command.exec(c.editor,{},c.event,!0)}),s}return n.prototype.exec=function(i,o,s){if(Array.isArray(i)){for(var c=i.length;c--;)if(this.exec(i[c],o,s))return!0;return!1}if(typeof i=="string"&&(i=this.commands[i]),!i||o&&o.$readOnly&&!i.readOnly||this.$checkCommandState!=!1&&i.isAvailable&&!i.isAvailable(o))return!1;var p={editor:o,command:i,args:s};return p.returnValue=this._emit("exec",p),this._signal("afterExec",p),p.returnValue!==!1},n.prototype.toggleRecording=function(i){if(!this.$inReplay)return i&&i._emit("changeStatus"),this.recording?(this.macro.pop(),this.off("exec",this.$addCommandToMacro),this.macro.length||(this.macro=this.oldMacro),this.recording=!1):(this.$addCommandToMacro||(this.$addCommandToMacro=function(o){this.macro.push([o.command,o.args])}.bind(this)),this.oldMacro=this.macro,this.macro=[],this.on("exec",this.$addCommandToMacro),this.recording=!0)},n.prototype.replay=function(i){if(!(this.$inReplay||!this.macro)){if(this.recording)return this.toggleRecording(i);try{this.$inReplay=!0,this.macro.forEach(function(o){typeof o=="string"?this.exec(o,i):this.exec(o[0],i,o[1])},this)}finally{this.$inReplay=!1}}},n.prototype.trimMacro=function(i){return i.map(function(o){return typeof o[0]!="string"&&(o[0]=o[0].name),o[1]||(o=o[0]),o})},n}(u);a.implement(f.prototype,r),h.CommandManager=f}),ace.define("ace/commands/default_commands",["require","exports","module","ace/lib/lang","ace/config","ace/range"],function(e,h,m){var g=e("../lib/lang"),a=e("../config"),u=e("../range").Range;function r(l,n){return{win:l,mac:n}}h.commands=[{name:"showSettingsMenu",description:"Show settings menu",bindKey:r("Ctrl-,","Command-,"),exec:function(l){a.loadModule("ace/ext/settings_menu",function(n){n.init(l),l.showSettingsMenu()})},readOnly:!0},{name:"goToNextError",description:"Go to next error",bindKey:r("Alt-E","F4"),exec:function(l){a.loadModule("ace/ext/error_marker",function(n){n.showErrorMarker(l,1)})},scrollIntoView:"animate",readOnly:!0},{name:"goToPreviousError",description:"Go to previous error",bindKey:r("Alt-Shift-E","Shift-F4"),exec:function(l){a.loadModule("ace/ext/error_marker",function(n){n.showErrorMarker(l,-1)})},scrollIntoView:"animate",readOnly:!0},{name:"selectall",description:"Select all",bindKey:r("Ctrl-A","Command-A"),exec:function(l){l.selectAll()},readOnly:!0},{name:"centerselection",description:"Center selection",bindKey:r(null,"Ctrl-L"),exec:function(l){l.centerSelection()},readOnly:!0},{name:"gotoline",description:"Go to line...",bindKey:r("Ctrl-L","Command-L"),exec:function(l,n){typeof n=="number"&&!isNaN(n)&&l.gotoLine(n),l.prompt({$type:"gotoLine"})},readOnly:!0},{name:"fold",bindKey:r("Alt-L|Ctrl-F1","Command-Alt-L|Command-F1"),exec:function(l){l.session.toggleFold(!1)},multiSelectAction:"forEach",scrollIntoView:"center",readOnly:!0},{name:"unfold",bindKey:r("Alt-Shift-L|Ctrl-Shift-F1","Command-Alt-Shift-L|Command-Shift-F1"),exec:function(l){l.session.toggleFold(!0)},multiSelectAction:"forEach",scrollIntoView:"center",readOnly:!0},{name:"toggleFoldWidget",description:"Toggle fold widget",bindKey:r("F2","F2"),exec:function(l){l.session.toggleFoldWidget()},multiSelectAction:"forEach",scrollIntoView:"center",readOnly:!0},{name:"toggleParentFoldWidget",description:"Toggle parent fold widget",bindKey:r("Alt-F2","Alt-F2"),exec:function(l){l.session.toggleFoldWidget(!0)},multiSelectAction:"forEach",scrollIntoView:"center",readOnly:!0},{name:"foldall",description:"Fold all",bindKey:r(null,"Ctrl-Command-Option-0"),exec:function(l){l.session.foldAll()},scrollIntoView:"center",readOnly:!0},{name:"foldAllComments",description:"Fold all comments",bindKey:r(null,"Ctrl-Command-Option-0"),exec:function(l){l.session.foldAllComments()},scrollIntoView:"center",readOnly:!0},{name:"foldOther",description:"Fold other",bindKey:r("Alt-0","Command-Option-0"),exec:function(l){l.session.foldAll(),l.session.unfold(l.selection.getAllRanges())},scrollIntoView:"center",readOnly:!0},{name:"unfoldall",description:"Unfold all",bindKey:r("Alt-Shift-0","Command-Option-Shift-0"),exec:function(l){l.session.unfold()},scrollIntoView:"center",readOnly:!0},{name:"findnext",description:"Find next",bindKey:r("Ctrl-K","Command-G"),exec:function(l){l.findNext()},multiSelectAction:"forEach",scrollIntoView:"center",readOnly:!0},{name:"findprevious",description:"Find previous",bindKey:r("Ctrl-Shift-K","Command-Shift-G"),exec:function(l){l.findPrevious()},multiSelectAction:"forEach",scrollIntoView:"center",readOnly:!0},{name:"selectOrFindNext",description:"Select or find next",bindKey:r("Alt-K","Ctrl-G"),exec:function(l){l.selection.isEmpty()?l.selection.selectWord():l.findNext()},readOnly:!0},{name:"selectOrFindPrevious",description:"Select or find previous",bindKey:r("Alt-Shift-K","Ctrl-Shift-G"),exec:function(l){l.selection.isEmpty()?l.selection.selectWord():l.findPrevious()},readOnly:!0},{name:"find",description:"Find",bindKey:r("Ctrl-F","Command-F"),exec:function(l){a.loadModule("ace/ext/searchbox",function(n){n.Search(l)})},readOnly:!0},{name:"overwrite",description:"Overwrite",bindKey:"Insert",exec:function(l){l.toggleOverwrite()},readOnly:!0},{name:"selecttostart",description:"Select to start",bindKey:r("Ctrl-Shift-Home","Command-Shift-Home|Command-Shift-Up"),exec:function(l){l.getSelection().selectFileStart()},multiSelectAction:"forEach",readOnly:!0,scrollIntoView:"animate",aceCommandGroup:"fileJump"},{name:"gotostart",description:"Go to start",bindKey:r("Ctrl-Home","Command-Home|Command-Up"),exec:function(l){l.navigateFileStart()},multiSelectAction:"forEach",readOnly:!0,scrollIntoView:"animate",aceCommandGroup:"fileJump"},{name:"selectup",description:"Select up",bindKey:r("Shift-Up","Shift-Up|Ctrl-Shift-P"),exec:function(l){l.getSelection().selectUp()},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"golineup",description:"Go line up",bindKey:r("Up","Up|Ctrl-P"),exec:function(l,n){l.navigateUp(n.times)},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"selecttoend",description:"Select to end",bindKey:r("Ctrl-Shift-End","Command-Shift-End|Command-Shift-Down"),exec:function(l){l.getSelection().selectFileEnd()},multiSelectAction:"forEach",readOnly:!0,scrollIntoView:"animate",aceCommandGroup:"fileJump"},{name:"gotoend",description:"Go to end",bindKey:r("Ctrl-End","Command-End|Command-Down"),exec:function(l){l.navigateFileEnd()},multiSelectAction:"forEach",readOnly:!0,scrollIntoView:"animate",aceCommandGroup:"fileJump"},{name:"selectdown",description:"Select down",bindKey:r("Shift-Down","Shift-Down|Ctrl-Shift-N"),exec:function(l){l.getSelection().selectDown()},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"golinedown",description:"Go line down",bindKey:r("Down","Down|Ctrl-N"),exec:function(l,n){l.navigateDown(n.times)},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"selectwordleft",description:"Select word left",bindKey:r("Ctrl-Shift-Left","Option-Shift-Left"),exec:function(l){l.getSelection().selectWordLeft()},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"gotowordleft",description:"Go to word left",bindKey:r("Ctrl-Left","Option-Left"),exec:function(l){l.navigateWordLeft()},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"selecttolinestart",description:"Select to line start",bindKey:r("Alt-Shift-Left","Command-Shift-Left|Ctrl-Shift-A"),exec:function(l){l.getSelection().selectLineStart()},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"gotolinestart",description:"Go to line start",bindKey:r("Alt-Left|Home","Command-Left|Home|Ctrl-A"),exec:function(l){l.navigateLineStart()},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"selectleft",description:"Select left",bindKey:r("Shift-Left","Shift-Left|Ctrl-Shift-B"),exec:function(l){l.getSelection().selectLeft()},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"gotoleft",description:"Go to left",bindKey:r("Left","Left|Ctrl-B"),exec:function(l,n){l.navigateLeft(n.times)},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"selectwordright",description:"Select word right",bindKey:r("Ctrl-Shift-Right","Option-Shift-Right"),exec:function(l){l.getSelection().selectWordRight()},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"gotowordright",description:"Go to word right",bindKey:r("Ctrl-Right","Option-Right"),exec:function(l){l.navigateWordRight()},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"selecttolineend",description:"Select to line end",bindKey:r("Alt-Shift-Right","Command-Shift-Right|Shift-End|Ctrl-Shift-E"),exec:function(l){l.getSelection().selectLineEnd()},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"gotolineend",description:"Go to line end",bindKey:r("Alt-Right|End","Command-Right|End|Ctrl-E"),exec:function(l){l.navigateLineEnd()},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"selectright",description:"Select right",bindKey:r("Shift-Right","Shift-Right"),exec:function(l){l.getSelection().selectRight()},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"gotoright",description:"Go to right",bindKey:r("Right","Right|Ctrl-F"),exec:function(l,n){l.navigateRight(n.times)},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"selectpagedown",description:"Select page down",bindKey:"Shift-PageDown",exec:function(l){l.selectPageDown()},readOnly:!0},{name:"pagedown",description:"Page down",bindKey:r(null,"Option-PageDown"),exec:function(l){l.scrollPageDown()},readOnly:!0},{name:"gotopagedown",description:"Go to page down",bindKey:r("PageDown","PageDown|Ctrl-V"),exec:function(l){l.gotoPageDown()},readOnly:!0},{name:"selectpageup",description:"Select page up",bindKey:"Shift-PageUp",exec:function(l){l.selectPageUp()},readOnly:!0},{name:"pageup",description:"Page up",bindKey:r(null,"Option-PageUp"),exec:function(l){l.scrollPageUp()},readOnly:!0},{name:"gotopageup",description:"Go to page up",bindKey:"PageUp",exec:function(l){l.gotoPageUp()},readOnly:!0},{name:"scrollup",description:"Scroll up",bindKey:r("Ctrl-Up",null),exec:function(l){l.renderer.scrollBy(0,-2*l.renderer.layerConfig.lineHeight)},readOnly:!0},{name:"scrolldown",description:"Scroll down",bindKey:r("Ctrl-Down",null),exec:function(l){l.renderer.scrollBy(0,2*l.renderer.layerConfig.lineHeight)},readOnly:!0},{name:"selectlinestart",description:"Select line start",bindKey:"Shift-Home",exec:function(l){l.getSelection().selectLineStart()},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"selectlineend",description:"Select line end",bindKey:"Shift-End",exec:function(l){l.getSelection().selectLineEnd()},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"togglerecording",description:"Toggle recording",bindKey:r("Ctrl-Alt-E","Command-Option-E"),exec:function(l){l.commands.toggleRecording(l)},readOnly:!0},{name:"replaymacro",description:"Replay macro",bindKey:r("Ctrl-Shift-E","Command-Shift-E"),exec:function(l){l.commands.replay(l)},readOnly:!0},{name:"jumptomatching",description:"Jump to matching",bindKey:r("Ctrl-\\|Ctrl-P","Command-\\"),exec:function(l){l.jumpToMatching()},multiSelectAction:"forEach",scrollIntoView:"animate",readOnly:!0},{name:"selecttomatching",description:"Select to matching",bindKey:r("Ctrl-Shift-\\|Ctrl-Shift-P","Command-Shift-\\"),exec:function(l){l.jumpToMatching(!0)},multiSelectAction:"forEach",scrollIntoView:"animate",readOnly:!0},{name:"expandToMatching",description:"Expand to matching",bindKey:r("Ctrl-Shift-M","Ctrl-Shift-M"),exec:function(l){l.jumpToMatching(!0,!0)},multiSelectAction:"forEach",scrollIntoView:"animate",readOnly:!0},{name:"passKeysToBrowser",description:"Pass keys to browser",bindKey:r(null,null),exec:function(){},passEvent:!0,readOnly:!0},{name:"copy",description:"Copy",exec:function(l){},readOnly:!0},{name:"cut",description:"Cut",exec:function(l){var n=l.$copyWithEmptySelection&&l.selection.isEmpty(),i=n?l.selection.getLineRange():l.selection.getRange();l._emit("cut",i),i.isEmpty()||l.session.remove(i),l.clearSelection()},scrollIntoView:"cursor",multiSelectAction:"forEach"},{name:"paste",description:"Paste",exec:function(l,n){l.$handlePaste(n)},scrollIntoView:"cursor"},{name:"removeline",description:"Remove line",bindKey:r("Ctrl-D","Command-D"),exec:function(l){l.removeLines()},scrollIntoView:"cursor",multiSelectAction:"forEachLine"},{name:"duplicateSelection",description:"Duplicate selection",bindKey:r("Ctrl-Shift-D","Command-Shift-D"),exec:function(l){l.duplicateSelection()},scrollIntoView:"cursor",multiSelectAction:"forEach"},{name:"sortlines",description:"Sort lines",bindKey:r("Ctrl-Alt-S","Command-Alt-S"),exec:function(l){l.sortLines()},scrollIntoView:"selection",multiSelectAction:"forEachLine"},{name:"togglecomment",description:"Toggle comment",bindKey:r("Ctrl-/","Command-/"),exec:function(l){l.toggleCommentLines()},multiSelectAction:"forEachLine",scrollIntoView:"selectionPart"},{name:"toggleBlockComment",description:"Toggle block comment",bindKey:r("Ctrl-Shift-/","Command-Shift-/"),exec:function(l){l.toggleBlockComment()},multiSelectAction:"forEach",scrollIntoView:"selectionPart"},{name:"modifyNumberUp",description:"Modify number up",bindKey:r("Ctrl-Shift-Up","Alt-Shift-Up"),exec:function(l){l.modifyNumber(1)},scrollIntoView:"cursor",multiSelectAction:"forEach"},{name:"modifyNumberDown",description:"Modify number down",bindKey:r("Ctrl-Shift-Down","Alt-Shift-Down"),exec:function(l){l.modifyNumber(-1)},scrollIntoView:"cursor",multiSelectAction:"forEach"},{name:"replace",description:"Replace",bindKey:r("Ctrl-H","Command-Option-F"),exec:function(l){a.loadModule("ace/ext/searchbox",function(n){n.Search(l,!0)})}},{name:"undo",description:"Undo",bindKey:r("Ctrl-Z","Command-Z"),exec:function(l){l.undo()}},{name:"redo",description:"Redo",bindKey:r("Ctrl-Shift-Z|Ctrl-Y","Command-Shift-Z|Command-Y"),exec:function(l){l.redo()}},{name:"copylinesup",description:"Copy lines up",bindKey:r("Alt-Shift-Up","Command-Option-Up"),exec:function(l){l.copyLinesUp()},scrollIntoView:"cursor"},{name:"movelinesup",description:"Move lines up",bindKey:r("Alt-Up","Option-Up"),exec:function(l){l.moveLinesUp()},scrollIntoView:"cursor"},{name:"copylinesdown",description:"Copy lines down",bindKey:r("Alt-Shift-Down","Command-Option-Down"),exec:function(l){l.copyLinesDown()},scrollIntoView:"cursor"},{name:"movelinesdown",description:"Move lines down",bindKey:r("Alt-Down","Option-Down"),exec:function(l){l.moveLinesDown()},scrollIntoView:"cursor"},{name:"del",description:"Delete",bindKey:r("Delete","Delete|Ctrl-D|Shift-Delete"),exec:function(l){l.remove("right")},multiSelectAction:"forEach",scrollIntoView:"cursor"},{name:"backspace",description:"Backspace",bindKey:r("Shift-Backspace|Backspace","Ctrl-Backspace|Shift-Backspace|Backspace|Ctrl-H"),exec:function(l){l.remove("left")},multiSelectAction:"forEach",scrollIntoView:"cursor"},{name:"cut_or_delete",description:"Cut or delete",bindKey:r("Shift-Delete",null),exec:function(l){if(l.selection.isEmpty())l.remove("left");else return!1},multiSelectAction:"forEach",scrollIntoView:"cursor"},{name:"removetolinestart",description:"Remove to line start",bindKey:r("Alt-Backspace","Command-Backspace"),exec:function(l){l.removeToLineStart()},multiSelectAction:"forEach",scrollIntoView:"cursor"},{name:"removetolineend",description:"Remove to line end",bindKey:r("Alt-Delete","Ctrl-K|Command-Delete"),exec:function(l){l.removeToLineEnd()},multiSelectAction:"forEach",scrollIntoView:"cursor"},{name:"removetolinestarthard",description:"Remove to line start hard",bindKey:r("Ctrl-Shift-Backspace",null),exec:function(l){var n=l.selection.getRange();n.start.column=0,l.session.remove(n)},multiSelectAction:"forEach",scrollIntoView:"cursor"},{name:"removetolineendhard",description:"Remove to line end hard",bindKey:r("Ctrl-Shift-Delete",null),exec:function(l){var n=l.selection.getRange();n.end.column=Number.MAX_VALUE,l.session.remove(n)},multiSelectAction:"forEach",scrollIntoView:"cursor"},{name:"removewordleft",description:"Remove word left",bindKey:r("Ctrl-Backspace","Alt-Backspace|Ctrl-Alt-Backspace"),exec:function(l){l.removeWordLeft()},multiSelectAction:"forEach",scrollIntoView:"cursor"},{name:"removewordright",description:"Remove word right",bindKey:r("Ctrl-Delete","Alt-Delete"),exec:function(l){l.removeWordRight()},multiSelectAction:"forEach",scrollIntoView:"cursor"},{name:"outdent",description:"Outdent",bindKey:r("Shift-Tab","Shift-Tab"),exec:function(l){l.blockOutdent()},multiSelectAction:"forEach",scrollIntoView:"selectionPart"},{name:"indent",description:"Indent",bindKey:r("Tab","Tab"),exec:function(l){l.indent()},multiSelectAction:"forEach",scrollIntoView:"selectionPart"},{name:"blockoutdent",description:"Block outdent",bindKey:r("Ctrl-[","Ctrl-["),exec:function(l){l.blockOutdent()},multiSelectAction:"forEachLine",scrollIntoView:"selectionPart"},{name:"blockindent",description:"Block indent",bindKey:r("Ctrl-]","Ctrl-]"),exec:function(l){l.blockIndent()},multiSelectAction:"forEachLine",scrollIntoView:"selectionPart"},{name:"insertstring",description:"Insert string",exec:function(l,n){l.insert(n)},multiSelectAction:"forEach",scrollIntoView:"cursor"},{name:"inserttext",description:"Insert text",exec:function(l,n){l.insert(g.stringRepeat(n.text||"",n.times||1))},multiSelectAction:"forEach",scrollIntoView:"cursor"},{name:"splitline",description:"Split line",bindKey:r(null,"Ctrl-O"),exec:function(l){l.splitLine()},multiSelectAction:"forEach",scrollIntoView:"cursor"},{name:"transposeletters",description:"Transpose letters",bindKey:r("Alt-Shift-X","Ctrl-T"),exec:function(l){l.transposeLetters()},multiSelectAction:function(l){l.transposeSelections(1)},scrollIntoView:"cursor"},{name:"touppercase",description:"To uppercase",bindKey:r("Ctrl-U","Ctrl-U"),exec:function(l){l.toUpperCase()},multiSelectAction:"forEach",scrollIntoView:"cursor"},{name:"tolowercase",description:"To lowercase",bindKey:r("Ctrl-Shift-U","Ctrl-Shift-U"),exec:function(l){l.toLowerCase()},multiSelectAction:"forEach",scrollIntoView:"cursor"},{name:"autoindent",description:"Auto Indent",bindKey:r(null,null),exec:function(l){l.autoIndent()},scrollIntoView:"animate"},{name:"expandtoline",description:"Expand to line",bindKey:r("Ctrl-Shift-L","Command-Shift-L"),exec:function(l){var n=l.selection.getRange();n.start.column=n.end.column=0,n.end.row++,l.selection.setRange(n,!1)},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"openlink",bindKey:r("Ctrl+F3","F3"),exec:function(l){l.openLink()}},{name:"joinlines",description:"Join lines",bindKey:r(null,null),exec:function(l){for(var n=l.selection.isBackwards(),i=n?l.selection.getSelectionLead():l.selection.getSelectionAnchor(),o=n?l.selection.getSelectionAnchor():l.selection.getSelectionLead(),s=l.session.doc.getLine(i.row).length,c=l.session.doc.getTextRange(l.selection.getRange()),p=c.replace(/\n\s*/," ").length,$=l.session.doc.getLine(i.row),v=i.row+1;v<=o.row+1;v++){var C=g.stringTrimLeft(g.stringTrimRight(l.session.doc.getLine(v)));C.length!==0&&(C=" "+C),$+=C}o.row+10?(l.selection.moveCursorTo(i.row,i.column),l.selection.selectTo(i.row,i.column+p)):(s=l.session.doc.getLine(i.row).length>s?s+1:s,l.selection.moveCursorTo(i.row,s))},multiSelectAction:"forEach",readOnly:!0},{name:"invertSelection",description:"Invert selection",bindKey:r(null,null),exec:function(l){var n=l.session.doc.getLength()-1,i=l.session.doc.getLine(n).length,o=l.selection.rangeList.ranges,s=[];o.length<1&&(o=[l.selection.getRange()]);for(var c=0;cf[l].column&&l++,o.unshift(l,0),f.splice.apply(f,o),this.$updateRows()}}},u.prototype.$updateRows=function(){var r=this.session.lineWidgets;if(!!r){var f=!0;r.forEach(function(l,n){if(l)for(f=!1,l.row=n;l.$oldWidget;)l.$oldWidget.row=n,l=l.$oldWidget}),f&&(this.session.lineWidgets=null)}},u.prototype.$registerLineWidget=function(r){this.session.lineWidgets||(this.session.lineWidgets=new Array(this.session.getLength()));var f=this.session.lineWidgets[r.row];return f&&(r.$oldWidget=f,f.el&&f.el.parentNode&&(f.el.parentNode.removeChild(f.el),f._inDocument=!1)),this.session.lineWidgets[r.row]=r,r},u.prototype.addLineWidget=function(r){if(this.$registerLineWidget(r),r.session=this.session,!this.editor)return r;var f=this.editor.renderer;r.html&&!r.el&&(r.el=g.createElement("div"),r.el.innerHTML=r.html),r.text&&!r.el&&(r.el=g.createElement("div"),r.el.textContent=r.text),r.el&&(g.addCssClass(r.el,"ace_lineWidgetContainer"),r.className&&g.addCssClass(r.el,r.className),r.el.style.position="absolute",r.el.style.zIndex="5",f.container.appendChild(r.el),r._inDocument=!0,r.coverGutter||(r.el.style.zIndex="3"),r.pixelHeight==null&&(r.pixelHeight=r.el.offsetHeight)),r.rowCount==null&&(r.rowCount=r.pixelHeight/f.layerConfig.lineHeight);var l=this.session.getFoldAt(r.row,0);if(r.$fold=l,l){var n=this.session.lineWidgets;r.row==l.end.row&&!n[l.start.row]?n[l.start.row]=r:r.hidden=!0}return this.session._emit("changeFold",{data:{start:{row:r.row}}}),this.$updateRows(),this.renderWidgets(null,f),this.onWidgetChanged(r),r},u.prototype.removeLineWidget=function(r){if(r._inDocument=!1,r.session=null,r.el&&r.el.parentNode&&r.el.parentNode.removeChild(r.el),r.editor&&r.editor.destroy)try{r.editor.destroy()}catch{}if(this.session.lineWidgets){var f=this.session.lineWidgets[r.row];if(f==r)this.session.lineWidgets[r.row]=r.$oldWidget,r.$oldWidget&&this.onWidgetChanged(r.$oldWidget);else for(;f;){if(f.$oldWidget==r){f.$oldWidget=r.$oldWidget;break}f=f.$oldWidget}}this.session._emit("changeFold",{data:{start:{row:r.row}}}),this.$updateRows()},u.prototype.getWidgetsAtRow=function(r){for(var f=this.session.lineWidgets,l=f&&f[r],n=[];l;)n.push(l),l=l.$oldWidget;return n},u.prototype.onWidgetChanged=function(r){this.session._changedWidgets.push(r),this.editor&&this.editor.renderer.updateFull()},u.prototype.measureWidgets=function(r,f){var l=this.session._changedWidgets,n=f.layerConfig;if(!(!l||!l.length)){for(var i=1/0,o=0;o0&&!n[i];)i--;this.firstRow=l.firstRow,this.lastRow=l.lastRow,f.$cursorLayer.config=l;for(var s=i;s<=o;s++){var c=n[s];if(!(!c||!c.el)){if(c.hidden){c.el.style.top=-100-(c.pixelHeight||0)+"px";continue}c._inDocument||(c._inDocument=!0,f.container.appendChild(c.el));var p=f.$cursorLayer.getPixelPosition({row:s,column:0},!0).top;c.coverLine||(p+=l.lineHeight*this.session.getRowLineCount(c.row)),c.el.style.top=p-l.offset+"px";var $=c.coverGutter?0:f.gutterWidth;c.fixedWidth||($-=f.scrollLeft),c.el.style.left=$+"px",c.fullWidth&&c.screenWidth&&(c.el.style.minWidth=l.width+2*l.padding+"px"),c.fixedWidth?c.el.style.right=f.scrollBar.getWidth()+"px":c.el.style.right=""}}}},u}();h.LineWidgets=a}),ace.define("ace/keyboard/gutter_handler",["require","exports","module","ace/lib/keys","ace/mouse/default_gutter_handler"],function(e,h,m){var g=e("../lib/keys"),a=e("../mouse/default_gutter_handler").GutterTooltip,u=function(){function f(l){this.editor=l,this.gutterLayer=l.renderer.$gutterLayer,this.element=l.renderer.$gutter,this.lines=l.renderer.$gutterLayer.$lines,this.activeRowIndex=null,this.activeLane=null,this.annotationTooltip=new a(this.editor)}return f.prototype.addListener=function(){this.element.addEventListener("keydown",this.$onGutterKeyDown.bind(this)),this.element.addEventListener("focusout",this.$blurGutter.bind(this)),this.editor.on("mousewheel",this.$blurGutter.bind(this))},f.prototype.removeListener=function(){this.element.removeEventListener("keydown",this.$onGutterKeyDown.bind(this)),this.element.removeEventListener("focusout",this.$blurGutter.bind(this)),this.editor.off("mousewheel",this.$blurGutter.bind(this))},f.prototype.$onGutterKeyDown=function(l){if(this.annotationTooltip.isOpen){l.preventDefault(),l.keyCode===g.escape&&this.annotationTooltip.hideTooltip();return}if(l.target===this.element){if(l.keyCode!=g.enter)return;l.preventDefault();var n=this.editor.getCursorPosition().row;this.editor.isRowVisible(n)||this.editor.scrollToLine(n,!0,!0),setTimeout(function(){var i=this.$rowToRowIndex(this.gutterLayer.$cursorCell.row),o=this.$findNearestFoldWidget(i),s=this.$findNearestAnnotation(i);if(!(o===null&&s===null)){if(o===null&&s!==null){this.activeRowIndex=s,this.activeLane="annotation",this.$focusAnnotation(this.activeRowIndex);return}if(o!==null&&s===null){this.activeRowIndex=o,this.activeLane="fold",this.$focusFoldWidget(this.activeRowIndex);return}if(Math.abs(s-i)0||l+n=0&&this.$isFoldWidgetVisible(l-n))return l-n;if(l+n<=this.lines.getLength()-1&&this.$isFoldWidgetVisible(l+n))return l+n}return null},f.prototype.$findNearestAnnotation=function(l){if(this.$isAnnotationVisible(l))return l;for(var n=0;l-n>0||l+n=0&&this.$isAnnotationVisible(l-n))return l-n;if(l+n<=this.lines.getLength()-1&&this.$isAnnotationVisible(l+n))return l+n}return null},f.prototype.$focusFoldWidget=function(l){if(l!=null){var n=this.$getFoldWidget(l);n.classList.add(this.editor.renderer.keyboardFocusClassName),n.focus()}},f.prototype.$focusAnnotation=function(l){if(l!=null){var n=this.$getAnnotation(l);n.classList.add(this.editor.renderer.keyboardFocusClassName),n.focus()}},f.prototype.$blurFoldWidget=function(l){var n=this.$getFoldWidget(l);n.classList.remove(this.editor.renderer.keyboardFocusClassName),n.blur()},f.prototype.$blurAnnotation=function(l){var n=this.$getAnnotation(l);n.classList.remove(this.editor.renderer.keyboardFocusClassName),n.blur()},f.prototype.$moveFoldWidgetUp=function(){for(var l=this.activeRowIndex;l>0;)if(l--,this.$isFoldWidgetVisible(l)){this.$blurFoldWidget(this.activeRowIndex),this.activeRowIndex=l,this.$focusFoldWidget(this.activeRowIndex);return}},f.prototype.$moveFoldWidgetDown=function(){for(var l=this.activeRowIndex;l0;)if(l--,this.$isAnnotationVisible(l)){this.$blurAnnotation(this.activeRowIndex),this.activeRowIndex=l,this.$focusAnnotation(this.activeRowIndex);return}},f.prototype.$moveAnnotationDown=function(){for(var l=this.activeRowIndex;l=S.length&&(S=void 0),{value:S&&S[q++],done:!S}}};throw new TypeError(w?"Object is not iterable.":"Symbol.iterator is not defined.")},a=e("./lib/oop"),u=e("./lib/dom"),r=e("./lib/lang"),f=e("./lib/useragent"),l=e("./keyboard/textinput").TextInput,n=e("./mouse/mouse_handler").MouseHandler,i=e("./mouse/fold_handler").FoldHandler,o=e("./keyboard/keybinding").KeyBinding,s=e("./edit_session").EditSession,c=e("./search").Search,p=e("./range").Range,$=e("./lib/event_emitter").EventEmitter,v=e("./commands/command_manager").CommandManager,C=e("./commands/default_commands").commands,y=e("./config"),_=e("./token_iterator").TokenIterator,b=e("./line_widgets").LineWidgets,E=e("./keyboard/gutter_handler").GutterKeyboardHandler,x=e("./config").nls,O=e("./clipboard"),M=e("./lib/keys"),k=function(){function S(w,L,q){this.session,this.$toDestroy=[];var A=w.getContainerElement();this.container=A,this.renderer=w,this.id="editor"+ ++S.$uid,this.commands=new v(f.isMac?"mac":"win",C),typeof document=="object"&&(this.textInput=new l(w.getTextAreaContainer(),this),this.renderer.textarea=this.textInput.getElement(),this.$mouseHandler=new n(this),new i(this)),this.keyBinding=new o(this),this.$search=new c().set({wrap:!0}),this.$historyTracker=this.$historyTracker.bind(this),this.commands.on("exec",this.$historyTracker),this.$initOperationListeners(),this._$emitInputEvent=r.delayedCall(function(){this._signal("input",{}),this.session&&!this.session.destroyed&&this.session.bgTokenizer.scheduleStart()}.bind(this)),this.on("change",function(I,F){F._$emitInputEvent.schedule(31)}),this.setSession(L||q&&q.session||new s("")),y.resetOptions(this),q&&this.setOptions(q),y._signal("editor",this)}return S.prototype.$initOperationListeners=function(){this.commands.on("exec",this.startOperation.bind(this),!0),this.commands.on("afterExec",this.endOperation.bind(this),!0),this.$opResetTimer=r.delayedCall(this.endOperation.bind(this,!0)),this.on("change",function(){this.curOp||(this.startOperation(),this.curOp.selectionBefore=this.$lastSel),this.curOp.docChanged=!0}.bind(this),!0),this.on("changeSelection",function(){this.curOp||(this.startOperation(),this.curOp.selectionBefore=this.$lastSel),this.curOp.selectionChanged=!0}.bind(this),!0)},S.prototype.startOperation=function(w){if(this.curOp){if(!w||this.curOp.command)return;this.prevOp=this.curOp}w||(this.previousCommand=null,w={}),this.$opResetTimer.schedule(),this.curOp=this.session.curOp={command:w.command||{},args:w.args,scrollTop:this.renderer.scrollTop},this.curOp.selectionBefore=this.selection.toJSON()},S.prototype.endOperation=function(w){if(this.curOp&&this.session){if(w&&w.returnValue===!1||!this.session)return this.curOp=null;if(w==!0&&this.curOp.command&&this.curOp.command.name=="mouse"||(this._signal("beforeEndOperation"),!this.curOp))return;var L=this.curOp.command,q=L&&L.scrollIntoView;if(q){switch(q){case"center-animate":q="animate";case"center":this.renderer.scrollCursorIntoView(null,.5);break;case"animate":case"cursor":this.renderer.scrollCursorIntoView();break;case"selectionPart":var A=this.selection.getRange(),I=this.renderer.layerConfig;(A.start.row>=I.lastRow||A.end.row<=I.firstRow)&&this.renderer.scrollSelectionIntoView(this.selection.anchor,this.selection.lead);break}q=="animate"&&this.renderer.animateScrolling(this.curOp.scrollTop)}var F=this.selection.toJSON();this.curOp.selectionAfter=F,this.$lastSel=this.selection.toJSON(),this.session.getUndoManager().addSelection(F),this.prevOp=this.curOp,this.curOp=null}},S.prototype.$historyTracker=function(w){if(!!this.$mergeUndoDeltas){var L=this.prevOp,q=this.$mergeableCommands,A=L.command&&w.command.name==L.command.name;if(w.command.name=="insertstring"){var I=w.args;this.mergeNextCommand===void 0&&(this.mergeNextCommand=!0),A=A&&this.mergeNextCommand&&(!/\s/.test(I)||/\s/.test(L.args)),this.mergeNextCommand=!0}else A=A&&q.indexOf(w.command.name)!==-1;this.$mergeUndoDeltas!="always"&&Date.now()-this.sequenceStartTime>2e3&&(A=!1),A?this.session.mergeUndoDeltas=!0:q.indexOf(w.command.name)!==-1&&(this.sequenceStartTime=Date.now())}},S.prototype.setKeyboardHandler=function(w,L){if(w&&typeof w=="string"&&w!="ace"){this.$keybindingId=w;var q=this;y.loadModule(["keybinding",w],function(A){q.$keybindingId==w&&q.keyBinding.setKeyboardHandler(A&&A.handler),L&&L()})}else this.$keybindingId=null,this.keyBinding.setKeyboardHandler(w),L&&L()},S.prototype.getKeyboardHandler=function(){return this.keyBinding.getKeyboardHandler()},S.prototype.setSession=function(w){if(this.session!=w){this.curOp&&this.endOperation(),this.curOp={};var L=this.session;if(L){this.session.off("change",this.$onDocumentChange),this.session.off("changeMode",this.$onChangeMode),this.session.off("tokenizerUpdate",this.$onTokenizerUpdate),this.session.off("changeTabSize",this.$onChangeTabSize),this.session.off("changeWrapLimit",this.$onChangeWrapLimit),this.session.off("changeWrapMode",this.$onChangeWrapMode),this.session.off("changeFold",this.$onChangeFold),this.session.off("changeFrontMarker",this.$onChangeFrontMarker),this.session.off("changeBackMarker",this.$onChangeBackMarker),this.session.off("changeBreakpoint",this.$onChangeBreakpoint),this.session.off("changeAnnotation",this.$onChangeAnnotation),this.session.off("changeOverwrite",this.$onCursorChange),this.session.off("changeScrollTop",this.$onScrollTopChange),this.session.off("changeScrollLeft",this.$onScrollLeftChange);var q=this.session.getSelection();q.off("changeCursor",this.$onCursorChange),q.off("changeSelection",this.$onSelectionChange)}this.session=w,w?(this.$onDocumentChange=this.onDocumentChange.bind(this),w.on("change",this.$onDocumentChange),this.renderer.setSession(w),this.$onChangeMode=this.onChangeMode.bind(this),w.on("changeMode",this.$onChangeMode),this.$onTokenizerUpdate=this.onTokenizerUpdate.bind(this),w.on("tokenizerUpdate",this.$onTokenizerUpdate),this.$onChangeTabSize=this.renderer.onChangeTabSize.bind(this.renderer),w.on("changeTabSize",this.$onChangeTabSize),this.$onChangeWrapLimit=this.onChangeWrapLimit.bind(this),w.on("changeWrapLimit",this.$onChangeWrapLimit),this.$onChangeWrapMode=this.onChangeWrapMode.bind(this),w.on("changeWrapMode",this.$onChangeWrapMode),this.$onChangeFold=this.onChangeFold.bind(this),w.on("changeFold",this.$onChangeFold),this.$onChangeFrontMarker=this.onChangeFrontMarker.bind(this),this.session.on("changeFrontMarker",this.$onChangeFrontMarker),this.$onChangeBackMarker=this.onChangeBackMarker.bind(this),this.session.on("changeBackMarker",this.$onChangeBackMarker),this.$onChangeBreakpoint=this.onChangeBreakpoint.bind(this),this.session.on("changeBreakpoint",this.$onChangeBreakpoint),this.$onChangeAnnotation=this.onChangeAnnotation.bind(this),this.session.on("changeAnnotation",this.$onChangeAnnotation),this.$onCursorChange=this.onCursorChange.bind(this),this.session.on("changeOverwrite",this.$onCursorChange),this.$onScrollTopChange=this.onScrollTopChange.bind(this),this.session.on("changeScrollTop",this.$onScrollTopChange),this.$onScrollLeftChange=this.onScrollLeftChange.bind(this),this.session.on("changeScrollLeft",this.$onScrollLeftChange),this.selection=w.getSelection(),this.selection.on("changeCursor",this.$onCursorChange),this.$onSelectionChange=this.onSelectionChange.bind(this),this.selection.on("changeSelection",this.$onSelectionChange),this.onChangeMode(),this.onCursorChange(),this.onScrollTopChange(),this.onScrollLeftChange(),this.onSelectionChange(),this.onChangeFrontMarker(),this.onChangeBackMarker(),this.onChangeBreakpoint(),this.onChangeAnnotation(),this.session.getUseWrapMode()&&this.renderer.adjustWrapLimit(),this.renderer.updateFull()):(this.selection=null,this.renderer.setSession(w)),this._signal("changeSession",{session:w,oldSession:L}),this.curOp=null,L&&L._signal("changeEditor",{oldEditor:this}),w&&w._signal("changeEditor",{editor:this}),w&&!w.destroyed&&w.bgTokenizer.scheduleStart()}},S.prototype.getSession=function(){return this.session},S.prototype.setValue=function(w,L){return this.session.doc.setValue(w),L?L==1?this.navigateFileEnd():L==-1&&this.navigateFileStart():this.selectAll(),w},S.prototype.getValue=function(){return this.session.getValue()},S.prototype.getSelection=function(){return this.selection},S.prototype.resize=function(w){this.renderer.onResize(w)},S.prototype.setTheme=function(w,L){this.renderer.setTheme(w,L)},S.prototype.getTheme=function(){return this.renderer.getTheme()},S.prototype.setStyle=function(w){this.renderer.setStyle(w)},S.prototype.unsetStyle=function(w){this.renderer.unsetStyle(w)},S.prototype.getFontSize=function(){return this.getOption("fontSize")||u.computedStyle(this.container).fontSize},S.prototype.setFontSize=function(w){this.setOption("fontSize",w)},S.prototype.$highlightBrackets=function(){if(!this.$highlightPending){var w=this;this.$highlightPending=!0,setTimeout(function(){w.$highlightPending=!1;var L=w.session;if(!(!L||L.destroyed)){L.$bracketHighlight&&(L.$bracketHighlight.markerIds.forEach(function(P){L.removeMarker(P)}),L.$bracketHighlight=null);var q=w.getCursorPosition(),A=w.getKeyboardHandler(),I=A&&A.$getDirectionForHighlight&&A.$getDirectionForHighlight(w),F=L.getMatchingBracketRanges(q,I);if(!F){var V=new _(L,q.row,q.column),R=V.getCurrentToken();if(R&&/\b(?:tag-open|tag-name)/.test(R.type)){var B=L.getMatchingTags(q);B&&(F=[B.openTagName,B.closeTagName])}}if(!F&&L.$mode.getMatching&&(F=L.$mode.getMatching(w.session)),!F){w.getHighlightIndentGuides()&&w.renderer.$textLayer.$highlightIndentGuide();return}var N="ace_bracket";Array.isArray(F)?F.length==1&&(N="ace_error_bracket"):F=[F],F.length==2&&(p.comparePoints(F[0].end,F[1].start)==0?F=[p.fromPoints(F[0].start,F[1].end)]:p.comparePoints(F[0].start,F[1].end)==0&&(F=[p.fromPoints(F[1].start,F[0].end)])),L.$bracketHighlight={ranges:F,markerIds:F.map(function(P){return L.addMarker(P,N,"text")})},w.getHighlightIndentGuides()&&w.renderer.$textLayer.$highlightIndentGuide()}},50)}},S.prototype.focus=function(){this.textInput.focus()},S.prototype.isFocused=function(){return this.textInput.isFocused()},S.prototype.blur=function(){this.textInput.blur()},S.prototype.onFocus=function(w){this.$isFocused||(this.$isFocused=!0,this.renderer.showCursor(),this.renderer.visualizeFocus(),this._emit("focus",w))},S.prototype.onBlur=function(w){!this.$isFocused||(this.$isFocused=!1,this.renderer.hideCursor(),this.renderer.visualizeBlur(),this._emit("blur",w))},S.prototype.$cursorChange=function(){this.renderer.updateCursor(),this.$highlightBrackets(),this.$updateHighlightActiveLine()},S.prototype.onDocumentChange=function(w){var L=this.session.$useWrapMode,q=w.start.row==w.end.row?w.end.row:1/0;this.renderer.updateLines(w.start.row,q,L),this._signal("change",w),this.$cursorChange()},S.prototype.onTokenizerUpdate=function(w){var L=w.data;this.renderer.updateLines(L.first,L.last)},S.prototype.onScrollTopChange=function(){this.renderer.scrollToY(this.session.getScrollTop())},S.prototype.onScrollLeftChange=function(){this.renderer.scrollToX(this.session.getScrollLeft())},S.prototype.onCursorChange=function(){this.$cursorChange(),this._signal("changeSelection")},S.prototype.$updateHighlightActiveLine=function(){var w=this.getSession(),L;if(this.$highlightActiveLine&&((this.$selectionStyle!="line"||!this.selection.isMultiLine())&&(L=this.getCursorPosition()),this.renderer.theme&&this.renderer.theme.$selectionColorConflict&&!this.selection.isEmpty()&&(L=!1),this.renderer.$maxLines&&this.session.getLength()===1&&!(this.renderer.$minLines>1)&&(L=!1)),w.$highlightLineMarker&&!L)w.removeMarker(w.$highlightLineMarker.id),w.$highlightLineMarker=null;else if(!w.$highlightLineMarker&&L){var q=new p(L.row,L.column,L.row,1/0);q.id=w.addMarker(q,"ace_active-line","screenLine"),w.$highlightLineMarker=q}else L&&(w.$highlightLineMarker.start.row=L.row,w.$highlightLineMarker.end.row=L.row,w.$highlightLineMarker.start.column=L.column,w._signal("changeBackMarker"))},S.prototype.onSelectionChange=function(w){var L=this.session;if(L.$selectionMarker&&L.removeMarker(L.$selectionMarker),L.$selectionMarker=null,this.selection.isEmpty())this.$updateHighlightActiveLine();else{var q=this.selection.getRange(),A=this.getSelectionStyle();L.$selectionMarker=L.addMarker(q,"ace_selection",A)}var I=this.$highlightSelectedWord&&this.$getSelectionHighLightRegexp();this.session.highlight(I),this._signal("changeSelection")},S.prototype.$getSelectionHighLightRegexp=function(){var w=this.session,L=this.getSelectionRange();if(!(L.isEmpty()||L.isMultiLine())){var q=L.start.column,A=L.end.column,I=w.getLine(L.start.row),F=I.substring(q,A);if(!(F.length>5e3||!/[\w\d]/.test(F))){var V=this.$search.$assembleRegExp({wholeWord:!0,caseSensitive:!0,needle:F}),R=I.substring(q-1,A+1);if(!!V.test(R))return V}}},S.prototype.onChangeFrontMarker=function(){this.renderer.updateFrontMarkers()},S.prototype.onChangeBackMarker=function(){this.renderer.updateBackMarkers()},S.prototype.onChangeBreakpoint=function(){this.renderer.updateBreakpoints()},S.prototype.onChangeAnnotation=function(){this.renderer.setAnnotations(this.session.getAnnotations())},S.prototype.onChangeMode=function(w){this.renderer.updateText(),this._emit("changeMode",w)},S.prototype.onChangeWrapLimit=function(){this.renderer.updateFull()},S.prototype.onChangeWrapMode=function(){this.renderer.onResize(!0)},S.prototype.onChangeFold=function(){this.$updateHighlightActiveLine(),this.renderer.updateFull()},S.prototype.getSelectedText=function(){return this.session.getTextRange(this.getSelectionRange())},S.prototype.getCopyText=function(){var w=this.getSelectedText(),L=this.session.doc.getNewLineCharacter(),q=!1;if(!w&&this.$copyWithEmptySelection){q=!0;for(var A=this.selection.getAllRanges(),I=0;IP.search(/\S|$/)){var R=P.substr(I.column).search(/\S|$/);q.doc.removeInLine(I.row,I.column,I.column+R)}}this.clearSelection();var B=I.column,N=q.getState(I.row),P=q.getLine(I.row),j=A.checkOutdent(N,P,w);if(q.insert(I,w),F&&F.selection&&(F.selection.length==2?this.selection.setSelectionRange(new p(I.row,B+F.selection[0],I.row,B+F.selection[1])):this.selection.setSelectionRange(new p(I.row+F.selection[0],F.selection[1],I.row+F.selection[2],F.selection[3]))),this.$enableAutoIndent){if(q.getDocument().isNewLine(w)){var D=A.getNextLineIndent(N,P.slice(0,I.column),q.getTabString());q.insert({row:I.row+1,column:0},D)}j&&A.autoOutdent(N,q,I.row)}},S.prototype.autoIndent=function(){for(var w=this.session,L=w.getMode(),q=this.selection.isEmpty()?[new p(0,0,w.doc.getLength()-1,0)]:this.selection.getAllRanges(),A="",I="",F="",V=w.getTabString(),R=0;R0&&(A=w.getState(P-1),I=w.getLine(P-1),F=L.getNextLineIndent(A,I,V));var j=w.getLine(P),D=L.$getIndent(j);if(F!==D){if(D.length>0){var W=new p(P,0,P,D.length);w.remove(W)}F.length>0&&w.insert({row:P,column:0},F)}L.autoOutdent(A,w,P)}},S.prototype.onTextInput=function(w,L){if(!L)return this.keyBinding.onTextInput(w);this.startOperation({command:{name:"insertstring"}});var q=this.applyComposition.bind(this,w,L);this.selection.rangeCount?this.forEachSelection(q):q(),this.endOperation()},S.prototype.applyComposition=function(w,L){if(L.extendLeft||L.extendRight){var q=this.selection.getRange();q.start.column-=L.extendLeft,q.end.column+=L.extendRight,q.start.column<0&&(q.start.row--,q.start.column+=this.session.getLine(q.start.row).length+1),this.selection.setRange(q),!w&&!q.isEmpty()&&this.remove()}if((w||!this.selection.isEmpty())&&this.insert(w,!0),L.restoreStart||L.restoreEnd){var q=this.selection.getRange();q.start.column-=L.restoreStart,q.end.column-=L.restoreEnd,this.selection.setRange(q)}},S.prototype.onCommandKey=function(w,L,q){return this.keyBinding.onCommandKey(w,L,q)},S.prototype.setOverwrite=function(w){this.session.setOverwrite(w)},S.prototype.getOverwrite=function(){return this.session.getOverwrite()},S.prototype.toggleOverwrite=function(){this.session.toggleOverwrite()},S.prototype.setScrollSpeed=function(w){this.setOption("scrollSpeed",w)},S.prototype.getScrollSpeed=function(){return this.getOption("scrollSpeed")},S.prototype.setDragDelay=function(w){this.setOption("dragDelay",w)},S.prototype.getDragDelay=function(){return this.getOption("dragDelay")},S.prototype.setSelectionStyle=function(w){this.setOption("selectionStyle",w)},S.prototype.getSelectionStyle=function(){return this.getOption("selectionStyle")},S.prototype.setHighlightActiveLine=function(w){this.setOption("highlightActiveLine",w)},S.prototype.getHighlightActiveLine=function(){return this.getOption("highlightActiveLine")},S.prototype.setHighlightGutterLine=function(w){this.setOption("highlightGutterLine",w)},S.prototype.getHighlightGutterLine=function(){return this.getOption("highlightGutterLine")},S.prototype.setHighlightSelectedWord=function(w){this.setOption("highlightSelectedWord",w)},S.prototype.getHighlightSelectedWord=function(){return this.$highlightSelectedWord},S.prototype.setAnimatedScroll=function(w){this.renderer.setAnimatedScroll(w)},S.prototype.getAnimatedScroll=function(){return this.renderer.getAnimatedScroll()},S.prototype.setShowInvisibles=function(w){this.renderer.setShowInvisibles(w)},S.prototype.getShowInvisibles=function(){return this.renderer.getShowInvisibles()},S.prototype.setDisplayIndentGuides=function(w){this.renderer.setDisplayIndentGuides(w)},S.prototype.getDisplayIndentGuides=function(){return this.renderer.getDisplayIndentGuides()},S.prototype.setHighlightIndentGuides=function(w){this.renderer.setHighlightIndentGuides(w)},S.prototype.getHighlightIndentGuides=function(){return this.renderer.getHighlightIndentGuides()},S.prototype.setShowPrintMargin=function(w){this.renderer.setShowPrintMargin(w)},S.prototype.getShowPrintMargin=function(){return this.renderer.getShowPrintMargin()},S.prototype.setPrintMarginColumn=function(w){this.renderer.setPrintMarginColumn(w)},S.prototype.getPrintMarginColumn=function(){return this.renderer.getPrintMarginColumn()},S.prototype.setReadOnly=function(w){this.setOption("readOnly",w)},S.prototype.getReadOnly=function(){return this.getOption("readOnly")},S.prototype.setBehavioursEnabled=function(w){this.setOption("behavioursEnabled",w)},S.prototype.getBehavioursEnabled=function(){return this.getOption("behavioursEnabled")},S.prototype.setWrapBehavioursEnabled=function(w){this.setOption("wrapBehavioursEnabled",w)},S.prototype.getWrapBehavioursEnabled=function(){return this.getOption("wrapBehavioursEnabled")},S.prototype.setShowFoldWidgets=function(w){this.setOption("showFoldWidgets",w)},S.prototype.getShowFoldWidgets=function(){return this.getOption("showFoldWidgets")},S.prototype.setFadeFoldWidgets=function(w){this.setOption("fadeFoldWidgets",w)},S.prototype.getFadeFoldWidgets=function(){return this.getOption("fadeFoldWidgets")},S.prototype.remove=function(w){this.selection.isEmpty()&&(w=="left"?this.selection.selectLeft():this.selection.selectRight());var L=this.getSelectionRange();if(this.getBehavioursEnabled()){var q=this.session,A=q.getState(L.start.row),I=q.getMode().transformAction(A,"deletion",this,q,L);if(L.end.column===0){var F=q.getTextRange(L);if(F[F.length-1]==` +`){var V=q.getLine(L.end.row);/^\s+$/.test(V)&&(L.end.column=V.length)}}I&&(L=I)}this.session.remove(L),this.clearSelection()},S.prototype.removeWordRight=function(){this.selection.isEmpty()&&this.selection.selectWordRight(),this.session.remove(this.getSelectionRange()),this.clearSelection()},S.prototype.removeWordLeft=function(){this.selection.isEmpty()&&this.selection.selectWordLeft(),this.session.remove(this.getSelectionRange()),this.clearSelection()},S.prototype.removeToLineStart=function(){this.selection.isEmpty()&&this.selection.selectLineStart(),this.selection.isEmpty()&&this.selection.selectLeft(),this.session.remove(this.getSelectionRange()),this.clearSelection()},S.prototype.removeToLineEnd=function(){this.selection.isEmpty()&&this.selection.selectLineEnd();var w=this.getSelectionRange();w.start.column==w.end.column&&w.start.row==w.end.row&&(w.end.column=0,w.end.row++),this.session.remove(w),this.clearSelection()},S.prototype.splitLine=function(){this.selection.isEmpty()||(this.session.remove(this.getSelectionRange()),this.clearSelection());var w=this.getCursorPosition();this.insert(` +`),this.moveCursorToPosition(w)},S.prototype.setGhostText=function(w,L){this.session.widgetManager||(this.session.widgetManager=new b(this.session),this.session.widgetManager.attach(this)),this.renderer.setGhostText(w,L)},S.prototype.removeGhostText=function(){!this.session.widgetManager||this.renderer.removeGhostText()},S.prototype.transposeLetters=function(){if(!!this.selection.isEmpty()){var w=this.getCursorPosition(),L=w.column;if(L!==0){var q=this.session.getLine(w.row),A,I;LR.toLowerCase()?1:0});for(var I=new p(0,0,0,0),A=w.first;A<=w.last;A++){var F=L.getLine(A);I.start.row=A,I.end.row=A,I.end.column=F.length,L.replace(I,q[A-w.first])}},S.prototype.toggleCommentLines=function(){var w=this.session.getState(this.getCursorPosition().row),L=this.$getSelectedRows();this.session.getMode().toggleCommentLines(w,this.session,L.first,L.last)},S.prototype.toggleBlockComment=function(){var w=this.getCursorPosition(),L=this.session.getState(w.row),q=this.getSelectionRange();this.session.getMode().toggleBlockComment(L,this.session,q,w)},S.prototype.getNumberAt=function(w,L){var q=/[\-]?[0-9]+(?:\.[0-9]+)?/g;q.lastIndex=0;for(var A=this.session.getLine(w);q.lastIndex=L){var F={value:I[0],start:I.index,end:I.index+I[0].length};return F}}return null},S.prototype.modifyNumber=function(w){var L=this.selection.getCursor().row,q=this.selection.getCursor().column,A=new p(L,q-1,L,q),I=this.session.getTextRange(A);if(!isNaN(parseFloat(I))&&isFinite(I)){var F=this.getNumberAt(L,q);if(F){var V=F.value.indexOf(".")>=0?F.start+F.value.indexOf(".")+1:F.end,R=F.start+F.value.length-V,B=parseFloat(F.value);B*=Math.pow(10,R),V!==F.end&&q=V&&F<=R&&(q=Z,B.selection.clearSelection(),B.moveCursorTo(w,V+A),B.selection.selectTo(w,R+A)),V=R});for(var N=this.$toggleWordPairs,P,j=0;j=R&&V<=B&&D.match(/((?:https?|ftp):\/\/[\S]+)/)){N=D.replace(/[\s:.,'";}\]]+$/,"");break}R=B}}catch(W){q={error:W}}finally{try{j&&!j.done&&(A=P.return)&&A.call(P)}finally{if(q)throw q.error}}return N},S.prototype.openLink=function(){var w=this.selection.getCursor(),L=this.findLinkAt(w.row,w.column);return L&&window.open(L,"_blank"),L!=null},S.prototype.removeLines=function(){var w=this.$getSelectedRows();this.session.removeFullLines(w.first,w.last),this.clearSelection()},S.prototype.duplicateSelection=function(){var w=this.selection,L=this.session,q=w.getRange(),A=w.isBackwards();if(q.isEmpty()){var I=q.start.row;L.duplicateLines(I,I)}else{var F=A?q.start:q.end,V=L.insert(F,L.getTextRange(q));q.start=F,q.end=V,w.setSelectionRange(q,A)}},S.prototype.moveLinesDown=function(){this.$moveLines(1,!1)},S.prototype.moveLinesUp=function(){this.$moveLines(-1,!1)},S.prototype.moveText=function(w,L,q){return this.session.moveText(w,L,q)},S.prototype.copyLinesUp=function(){this.$moveLines(-1,!0)},S.prototype.copyLinesDown=function(){this.$moveLines(1,!0)},S.prototype.$moveLines=function(w,L){var q,A,I=this.selection;if(!I.inMultiSelectMode||this.inVirtualSelectionMode){var F=I.toOrientedRange();q=this.$getSelectedRows(F),A=this.session.$moveLines(q.first,q.last,L?0:w),L&&w==-1&&(A=0),F.moveBy(A,0),I.fromOrientedRange(F)}else{var V=I.rangeList.ranges;I.rangeList.detach(this.session),this.inVirtualSelectionMode=!0;for(var R=0,B=0,N=V.length,P=0;PW+1)break;W=H.last}for(P--,R=this.session.$moveLines(D,W,L?0:w),L&&w==-1&&(j=P+1);j<=P;)V[j].moveBy(R,0),j++;L||(R=0),B+=R}I.fromOrientedRange(I.ranges[0]),I.rangeList.attach(this.session),this.inVirtualSelectionMode=!1}},S.prototype.$getSelectedRows=function(w){return w=(w||this.getSelectionRange()).collapseRows(),{first:this.session.getRowFoldStart(w.start.row),last:this.session.getRowFoldEnd(w.end.row)}},S.prototype.onCompositionStart=function(w){this.renderer.showComposition(w)},S.prototype.onCompositionUpdate=function(w){this.renderer.setCompositionText(w)},S.prototype.onCompositionEnd=function(){this.renderer.hideComposition()},S.prototype.getFirstVisibleRow=function(){return this.renderer.getFirstVisibleRow()},S.prototype.getLastVisibleRow=function(){return this.renderer.getLastVisibleRow()},S.prototype.isRowVisible=function(w){return w>=this.getFirstVisibleRow()&&w<=this.getLastVisibleRow()},S.prototype.isRowFullyVisible=function(w){return w>=this.renderer.getFirstFullyVisibleRow()&&w<=this.renderer.getLastFullyVisibleRow()},S.prototype.$getVisibleRowCount=function(){return this.renderer.getScrollBottomRow()-this.renderer.getScrollTopRow()+1},S.prototype.$moveByPage=function(w,L){var q=this.renderer,A=this.renderer.layerConfig,I=w*Math.floor(A.height/A.lineHeight);L===!0?this.selection.$moveSelection(function(){this.moveCursorBy(I,0)}):L===!1&&(this.selection.moveCursorBy(I,0),this.selection.clearSelection());var F=q.scrollTop;q.scrollBy(0,I*A.lineHeight),L!=null&&q.scrollCursorIntoView(null,.5),q.animateScrolling(F)},S.prototype.selectPageDown=function(){this.$moveByPage(1,!0)},S.prototype.selectPageUp=function(){this.$moveByPage(-1,!0)},S.prototype.gotoPageDown=function(){this.$moveByPage(1,!1)},S.prototype.gotoPageUp=function(){this.$moveByPage(-1,!1)},S.prototype.scrollPageDown=function(){this.$moveByPage(1)},S.prototype.scrollPageUp=function(){this.$moveByPage(-1)},S.prototype.scrollToRow=function(w){this.renderer.scrollToRow(w)},S.prototype.scrollToLine=function(w,L,q,A){this.renderer.scrollToLine(w,L,q,A)},S.prototype.centerSelection=function(){var w=this.getSelectionRange(),L={row:Math.floor(w.start.row+(w.end.row-w.start.row)/2),column:Math.floor(w.start.column+(w.end.column-w.start.column)/2)};this.renderer.alignCursor(L,.5)},S.prototype.getCursorPosition=function(){return this.selection.getCursor()},S.prototype.getCursorPositionScreen=function(){return this.session.documentToScreenPosition(this.getCursorPosition())},S.prototype.getSelectionRange=function(){return this.selection.getRange()},S.prototype.selectAll=function(){this.selection.selectAll()},S.prototype.clearSelection=function(){this.selection.clearSelection()},S.prototype.moveCursorTo=function(w,L){this.selection.moveCursorTo(w,L)},S.prototype.moveCursorToPosition=function(w){this.selection.moveCursorToPosition(w)},S.prototype.jumpToMatching=function(w,L){var q=this.getCursorPosition(),A=new _(this.session,q.row,q.column),I=A.getCurrentToken(),F=0;I&&I.type.indexOf("tag-name")!==-1&&(I=A.stepBackward());var V=I||A.stepForward();if(!!V){var R,B=!1,N={},P=q.column-V.start,j,D={")":"(","(":"(","]":"[","[":"[","{":"{","}":"{"};do{if(V.value.match(/[{}()\[\]]/g)){for(;P1?N[V.value]++:I.value==="=0;--F)this.$tryReplace(q[F],w)&&A++;return this.selection.setSelectionRange(I),A},S.prototype.$tryReplace=function(w,L){var q=this.session.getTextRange(w);return L=this.$search.replace(q,L),L!==null?(w.end=this.session.replace(w,L),w):null},S.prototype.getLastSearchOptions=function(){return this.$search.getOptions()},S.prototype.find=function(w,L,q){L||(L={}),typeof w=="string"||w instanceof RegExp?L.needle=w:typeof w=="object"&&a.mixin(L,w);var A=this.selection.getRange();L.needle==null&&(w=this.session.getTextRange(A)||this.$search.$options.needle,w||(A=this.session.getWordRange(A.start.row,A.start.column),w=this.session.getTextRange(A)),this.$search.set({needle:w})),this.$search.set(L),L.start||this.$search.set({start:A});var I=this.$search.find(this.session);if(L.preventScroll)return I;if(I)return this.revealRange(I,q),I;L.backwards?A.start=A.end:A.end=A.start,this.selection.setRange(A)},S.prototype.findNext=function(w,L){this.find({skipCurrent:!0,backwards:!1},w,L)},S.prototype.findPrevious=function(w,L){this.find(w,{skipCurrent:!0,backwards:!0},L)},S.prototype.revealRange=function(w,L){this.session.unfold(w),this.selection.setSelectionRange(w);var q=this.renderer.scrollTop;this.renderer.scrollSelectionIntoView(w.start,w.end,.5),L!==!1&&this.renderer.animateScrolling(q)},S.prototype.undo=function(){this.session.getUndoManager().undo(this.session),this.renderer.scrollCursorIntoView(null,.5)},S.prototype.redo=function(){this.session.getUndoManager().redo(this.session),this.renderer.scrollCursorIntoView(null,.5)},S.prototype.destroy=function(){this.$toDestroy&&(this.$toDestroy.forEach(function(w){w.destroy()}),this.$toDestroy=null),this.$mouseHandler&&this.$mouseHandler.destroy(),this.renderer.destroy(),this._signal("destroy",this),this.session&&this.session.destroy(),this._$emitInputEvent&&this._$emitInputEvent.cancel(),this.removeAllListeners()},S.prototype.setAutoScrollEditorIntoView=function(w){if(!!w){var L,q=this,A=!1;this.$scrollAnchor||(this.$scrollAnchor=document.createElement("div"));var I=this.$scrollAnchor;I.style.cssText="position:absolute",this.container.insertBefore(I,this.container.firstChild);var F=this.on("changeSelection",function(){A=!0}),V=this.renderer.on("beforeRender",function(){A&&(L=q.renderer.container.getBoundingClientRect())}),R=this.renderer.on("afterRender",function(){if(A&&L&&(q.isFocused()||q.searchBox&&q.searchBox.isFocused())){var B=q.renderer,N=B.$cursorLayer.$pixelPos,P=B.layerConfig,j=N.top-P.offset;N.top>=0&&j+L.top<0?A=!0:N.topwindow.innerHeight?A=!1:A=null,A!=null&&(I.style.top=j+"px",I.style.left=N.left+"px",I.style.height=P.lineHeight+"px",I.scrollIntoView(A)),A=L=null}});this.setAutoScrollEditorIntoView=function(B){B||(delete this.setAutoScrollEditorIntoView,this.off("changeSelection",F),this.renderer.off("afterRender",R),this.renderer.off("beforeRender",V))}}},S.prototype.$resetCursorStyle=function(){var w=this.$cursorStyle||"ace",L=this.renderer.$cursorLayer;!L||(L.setSmoothBlinking(/smooth/.test(w)),L.isBlinking=!this.$readOnly&&w!="wide",u.setCssClass(L.element,"ace_slim-cursors",/slim/.test(w)))},S.prototype.prompt=function(w,L,q){var A=this;y.loadModule("ace/ext/prompt",function(I){I.prompt(A,w,L,q)})},S}();k.$uid=0,k.prototype.curOp=null,k.prototype.prevOp={},k.prototype.$mergeableCommands=["backspace","del","insertstring"],k.prototype.$toggleWordPairs=[["first","last"],["true","false"],["yes","no"],["width","height"],["top","bottom"],["right","left"],["on","off"],["x","y"],["get","set"],["max","min"],["horizontal","vertical"],["show","hide"],["add","remove"],["up","down"],["before","after"],["even","odd"],["in","out"],["inside","outside"],["next","previous"],["increase","decrease"],["attach","detach"],["&&","||"],["==","!="]],a.implement(k.prototype,$),y.defineOptions(k.prototype,"editor",{selectionStyle:{set:function(S){this.onSelectionChange(),this._signal("changeSelectionStyle",{data:S})},initialValue:"line"},highlightActiveLine:{set:function(){this.$updateHighlightActiveLine()},initialValue:!0},highlightSelectedWord:{set:function(S){this.$onSelectionChange()},initialValue:!0},readOnly:{set:function(S){this.textInput.setReadOnly(S),this.$resetCursorStyle()},initialValue:!1},copyWithEmptySelection:{set:function(S){this.textInput.setCopyWithEmptySelection(S)},initialValue:!1},cursorStyle:{set:function(S){this.$resetCursorStyle()},values:["ace","slim","smooth","wide"],initialValue:"ace"},mergeUndoDeltas:{values:[!1,!0,"always"],initialValue:!0},behavioursEnabled:{initialValue:!0},wrapBehavioursEnabled:{initialValue:!0},enableAutoIndent:{initialValue:!0},autoScrollEditorIntoView:{set:function(S){this.setAutoScrollEditorIntoView(S)}},keyboardHandler:{set:function(S){this.setKeyboardHandler(S)},get:function(){return this.$keybindingId},handlesSet:!0},value:{set:function(S){this.session.setValue(S)},get:function(){return this.getValue()},handlesSet:!0,hidden:!0},session:{set:function(S){this.setSession(S)},get:function(){return this.session},handlesSet:!0,hidden:!0},showLineNumbers:{set:function(S){this.renderer.$gutterLayer.setShowLineNumbers(S),this.renderer.$loop.schedule(this.renderer.CHANGE_GUTTER),S&&this.$relativeLineNumbers?T.attach(this):T.detach(this)},initialValue:!0},relativeLineNumbers:{set:function(S){this.$showLineNumbers&&S?T.attach(this):T.detach(this)}},placeholder:{set:function(S){this.$updatePlaceholder||(this.$updatePlaceholder=function(){var w=this.session&&(this.renderer.$composition||this.session.getLength()>1||this.session.getLine(0).length>0);if(w&&this.renderer.placeholderNode)this.renderer.off("afterRender",this.$updatePlaceholder),u.removeCssClass(this.container,"ace_hasPlaceholder"),this.renderer.placeholderNode.remove(),this.renderer.placeholderNode=null;else if(!w&&!this.renderer.placeholderNode){this.renderer.on("afterRender",this.$updatePlaceholder),u.addCssClass(this.container,"ace_hasPlaceholder");var L=u.createElement("div");L.className="ace_placeholder",L.textContent=this.$placeholder||"",this.renderer.placeholderNode=L,this.renderer.content.appendChild(this.renderer.placeholderNode)}else!w&&this.renderer.placeholderNode&&(this.renderer.placeholderNode.textContent=this.$placeholder||"")}.bind(this),this.on("input",this.$updatePlaceholder)),this.$updatePlaceholder()}},enableKeyboardAccessibility:{set:function(S){var w={name:"blurTextInput",description:"Set focus to the editor content div to allow tabbing through the page",bindKey:"Esc",exec:function(A){A.blur(),A.renderer.scroller.focus()},readOnly:!0},L=function(A){if(A.target==this.renderer.scroller&&A.keyCode===M.enter){A.preventDefault();var I=this.getCursorPosition().row;this.isRowVisible(I)||this.scrollToLine(I,!0,!0),this.focus()}},q;S?(this.renderer.enableKeyboardAccessibility=!0,this.renderer.keyboardFocusClassName="ace_keyboard-focus",this.textInput.getElement().setAttribute("tabindex",-1),this.textInput.setNumberOfExtraLines(f.isWin?3:0),this.renderer.scroller.setAttribute("tabindex",0),this.renderer.scroller.setAttribute("role","group"),this.renderer.scroller.setAttribute("aria-roledescription",x("editor")),this.renderer.scroller.classList.add(this.renderer.keyboardFocusClassName),this.renderer.scroller.setAttribute("aria-label",x("Editor content, press Enter to start editing, press Escape to exit")),this.renderer.scroller.addEventListener("keyup",L.bind(this)),this.commands.addCommand(w),this.renderer.$gutter.setAttribute("tabindex",0),this.renderer.$gutter.setAttribute("aria-hidden",!1),this.renderer.$gutter.setAttribute("role","group"),this.renderer.$gutter.setAttribute("aria-roledescription",x("editor")),this.renderer.$gutter.setAttribute("aria-label",x("Editor gutter, press Enter to interact with controls using arrow keys, press Escape to exit")),this.renderer.$gutter.classList.add(this.renderer.keyboardFocusClassName),this.renderer.content.setAttribute("aria-hidden",!0),q||(q=new E(this)),q.addListener()):(this.renderer.enableKeyboardAccessibility=!1,this.textInput.getElement().setAttribute("tabindex",0),this.textInput.setNumberOfExtraLines(0),this.renderer.scroller.setAttribute("tabindex",-1),this.renderer.scroller.removeAttribute("role"),this.renderer.scroller.removeAttribute("aria-roledescription"),this.renderer.scroller.classList.remove(this.renderer.keyboardFocusClassName),this.renderer.scroller.removeAttribute("aria-label"),this.renderer.scroller.removeEventListener("keyup",L.bind(this)),this.commands.removeCommand(w),this.renderer.content.removeAttribute("aria-hidden"),this.renderer.$gutter.setAttribute("tabindex",-1),this.renderer.$gutter.setAttribute("aria-hidden",!0),this.renderer.$gutter.removeAttribute("role"),this.renderer.$gutter.removeAttribute("aria-roledescription"),this.renderer.$gutter.removeAttribute("aria-label"),this.renderer.$gutter.classList.remove(this.renderer.keyboardFocusClassName),q&&q.removeListener())},initialValue:!1},customScrollbar:"renderer",hScrollBarAlwaysVisible:"renderer",vScrollBarAlwaysVisible:"renderer",highlightGutterLine:"renderer",animatedScroll:"renderer",showInvisibles:"renderer",showPrintMargin:"renderer",printMarginColumn:"renderer",printMargin:"renderer",fadeFoldWidgets:"renderer",showFoldWidgets:"renderer",displayIndentGuides:"renderer",highlightIndentGuides:"renderer",showGutter:"renderer",fontSize:"renderer",fontFamily:"renderer",maxLines:"renderer",minLines:"renderer",scrollPastEnd:"renderer",fixedWidthGutter:"renderer",theme:"renderer",hasCssTransforms:"renderer",maxPixelHeight:"renderer",useTextareaForIME:"renderer",useResizeObserver:"renderer",useSvgGutterIcons:"renderer",showFoldedAnnotations:"renderer",scrollSpeed:"$mouseHandler",dragDelay:"$mouseHandler",dragEnabled:"$mouseHandler",focusTimeout:"$mouseHandler",tooltipFollowsMouse:"$mouseHandler",firstLineNumber:"session",overwrite:"session",newLineMode:"session",useWorker:"session",useSoftTabs:"session",navigateWithinSoftTabs:"session",tabSize:"session",wrap:"session",indentedSoftWrap:"session",foldStyle:"session",mode:"session"});var T={getText:function(S,w){return(Math.abs(S.selection.lead.row-w)||w+1+(w<9?"\xB7":""))+""},getWidth:function(S,w,L){return Math.max(w.toString().length,(L.lastRow+1).toString().length,2)*L.characterWidth},update:function(S,w){w.renderer.$loop.schedule(w.renderer.CHANGE_GUTTER)},attach:function(S){S.renderer.$gutterLayer.$renderer=this,S.on("changeSelection",this.update),this.update(null,S)},detach:function(S){S.renderer.$gutterLayer.$renderer==this&&(S.renderer.$gutterLayer.$renderer=null),S.off("changeSelection",this.update),this.update(null,S)}};h.Editor=k}),ace.define("ace/layer/lines",["require","exports","module","ace/lib/dom"],function(e,h,m){var g=e("../lib/dom"),a=function(){function u(r,f){this.element=r,this.canvasHeight=f||5e5,this.element.style.height=this.canvasHeight*2+"px",this.cells=[],this.cellCache=[],this.$offsetCoefficient=0}return u.prototype.moveContainer=function(r){g.translate(this.element,0,-(r.firstRowScreen*r.lineHeight%this.canvasHeight)-r.offset*this.$offsetCoefficient)},u.prototype.pageChanged=function(r,f){return Math.floor(r.firstRowScreen*r.lineHeight/this.canvasHeight)!==Math.floor(f.firstRowScreen*f.lineHeight/this.canvasHeight)},u.prototype.computeLineTop=function(r,f,l){var n=f.firstRowScreen*f.lineHeight,i=Math.floor(n/this.canvasHeight),o=l.documentToScreenRow(r,0)*f.lineHeight;return o-i*this.canvasHeight},u.prototype.computeLineHeight=function(r,f,l){return f.lineHeight*l.getRowLineCount(r)},u.prototype.getLength=function(){return this.cells.length},u.prototype.get=function(r){return this.cells[r]},u.prototype.shift=function(){this.$cacheCell(this.cells.shift())},u.prototype.pop=function(){this.$cacheCell(this.cells.pop())},u.prototype.push=function(r){if(Array.isArray(r)){this.cells.push.apply(this.cells,r);for(var f=g.createFragment(this.element),l=0;lC&&(b=v.end.row+1,v=c.getNextFoldLine(b,v),C=v?v.start.row:1/0),b>$){for(;this.$lines.getLength()>_+1;)this.$lines.pop();break}y=this.$lines.get(++_),y?y.row=b:(y=this.$lines.createCell(b,s,this.session,i),this.$lines.push(y)),this.$renderCell(y,s,v,b),b++}this._signal("afterRender"),this.$updateGutterWidth(s)},o.prototype.$updateGutterWidth=function(s){var c=this.session,p=c.gutterRenderer||this.$renderer,$=c.$firstLineNumber,v=this.$lines.last()?this.$lines.last().text:"";(this.$fixedWidth||c.$useWrapMode)&&(v=c.getLength()+$-1);var C=p?p.getWidth(c,v,s):v.toString().length*s.characterWidth,y=this.$padding||this.$computePadding();C+=y.left+y.right,C!==this.gutterWidth&&!isNaN(C)&&(this.gutterWidth=C,this.element.parentNode.style.width=this.element.style.width=Math.ceil(this.gutterWidth)+"px",this._signal("changeGutterWidth",C))},o.prototype.$updateCursorRow=function(){if(!!this.$highlightGutterLine){var s=this.session.selection.getCursor();this.$cursorRow!==s.row&&(this.$cursorRow=s.row)}},o.prototype.updateLineHighlight=function(){if(!!this.$highlightGutterLine){var s=this.session.selection.cursor.row;if(this.$cursorRow=s,!(this.$cursorCell&&this.$cursorCell.row==s)){this.$cursorCell&&(this.$cursorCell.element.className=this.$cursorCell.element.className.replace("ace_gutter-active-line ",""));var c=this.$lines.cells;this.$cursorCell=null;for(var p=0;p=this.$cursorRow){if($.row>this.$cursorRow){var v=this.session.getFoldLine(this.$cursorRow);if(p>0&&v&&v.start.row==c[p-1].row)$=c[p-1];else break}$.element.className="ace_gutter-active-line "+$.element.className,this.$cursorCell=$;break}}}}},o.prototype.scrollLines=function(s){var c=this.config;if(this.config=s,this.$updateCursorRow(),this.$lines.pageChanged(c,s))return this.update(s);this.$lines.moveContainer(s);var p=Math.min(s.lastRow+s.gutterOffset,this.session.getLength()-1),$=this.oldLastRow;if(this.oldLastRow=p,!c||$0;v--)this.$lines.shift();if($>p)for(var v=this.session.getFoldedRowCount(p+1,$);v>0;v--)this.$lines.pop();s.firstRow$&&this.$lines.push(this.$renderLines(s,$+1,p)),this.updateLineHighlight(),this._signal("afterRender"),this.$updateGutterWidth(s)},o.prototype.$renderLines=function(s,c,p){for(var $=[],v=c,C=this.session.getNextFoldLine(v),y=C?C.start.row:1/0;v>y&&(v=C.end.row+1,C=this.session.getNextFoldLine(v,C),y=C?C.start.row:1/0),!(v>p);){var _=this.$lines.createCell(v,s,this.session,i);this.$renderCell(_,s,C,v),$.push(_),v++}return $},o.prototype.$renderCell=function(s,c,p,$){var v=s.element,C=this.session,y=v.childNodes[0],_=v.childNodes[1],b=v.childNodes[2],E=b.firstChild,x=C.$firstLineNumber,O=C.$breakpoints,M=C.$decorations,k=C.gutterRenderer||this.$renderer,T=this.$showFoldWidgets&&C.foldWidgets,S=p?p.start.row:Number.MAX_VALUE,w=c.lineHeight+"px",L=this.$useSvgGutterIcons?"ace_gutter-cell_svg-icons ":"ace_gutter-cell ",q=this.$useSvgGutterIcons?"ace_icon_svg":"ace_icon",A=(k?k.getText(C,$):$+x).toString();if(this.$highlightGutterLine&&($==this.$cursorRow||p&&$=S&&this.$cursorRow<=p.end.row)&&(L+="ace_gutter-active-line ",this.$cursorCell!=s&&(this.$cursorCell&&(this.$cursorCell.element.className=this.$cursorCell.element.className.replace("ace_gutter-active-line ","")),this.$cursorCell=s)),O[$]&&(L+=O[$]),M[$]&&(L+=M[$]),this.$annotations[$]&&$!==S&&(L+=this.$annotations[$].className),T){var I=T[$];I==null&&(I=T[$]=C.getFoldWidget($))}if(I){var F="ace_fold-widget ace_"+I,V=I=="start"&&$==S&&$p.right-c.right)return"foldWidgets"},o}();n.prototype.$fixedWidth=!1,n.prototype.$highlightGutterLine=!0,n.prototype.$renderer="",n.prototype.$showLineNumbers=!0,n.prototype.$showFoldWidgets=!0,a.implement(n.prototype,r);function i(o){var s=document.createTextNode("");o.appendChild(s);var c=g.createElement("span");o.appendChild(c);var p=g.createElement("span");o.appendChild(p);var $=g.createElement("span");return p.appendChild($),o}h.Gutter=n}),ace.define("ace/layer/marker",["require","exports","module","ace/range","ace/lib/dom"],function(e,h,m){var g=e("../range").Range,a=e("../lib/dom"),u=function(){function f(l){this.element=a.createElement("div"),this.element.className="ace_layer ace_marker-layer",l.appendChild(this.element)}return f.prototype.setPadding=function(l){this.$padding=l},f.prototype.setSession=function(l){this.session=l},f.prototype.setMarkers=function(l){this.markers=l},f.prototype.elt=function(l,n){var i=this.i!=-1&&this.element.childNodes[this.i];i?this.i++:(i=document.createElement("div"),this.element.appendChild(i),this.i=-1),i.style.cssText=n,i.className=l},f.prototype.update=function(l){if(!!l){this.config=l,this.i=0;var n;for(var i in this.markers){var o=this.markers[i];if(!o.range){o.update(n,this,this.session,l);continue}var s=o.range.clipRows(l.firstRow,l.lastRow);if(!s.isEmpty())if(s=s.toScreenRange(this.session),o.renderer){var c=this.$getTop(s.start.row,l),p=this.$padding+s.start.column*l.characterWidth;o.renderer(n,s,p,c,l)}else o.type=="fullLine"?this.drawFullLineMarker(n,s,o.clazz,l):o.type=="screenLine"?this.drawScreenLineMarker(n,s,o.clazz,l):s.isMultiLine()?o.type=="text"?this.drawTextMarker(n,s,o.clazz,l):this.drawMultiLineMarker(n,s,o.clazz,l):this.drawSingleLineMarker(n,s,o.clazz+" ace_start ace_br15",l)}if(this.i!=-1)for(;this.i_,v==$),o,v==$?0:1,s)},f.prototype.drawMultiLineMarker=function(l,n,i,o,s){var c=this.$padding,p=o.lineHeight,$=this.$getTop(n.start.row,o),v=c+n.start.column*o.characterWidth;if(s=s||"",this.session.$bidiHandler.isBidiRow(n.start.row)){var C=n.clone();C.end.row=C.start.row,C.end.column=this.session.getLine(C.start.row).length,this.drawBidiSingleLineMarker(l,C,i+" ace_br1 ace_start",o,null,s)}else this.elt(i+" ace_br1 ace_start","height:"+p+"px;right:0;top:"+$+"px;left:"+v+"px;"+(s||""));if(this.session.$bidiHandler.isBidiRow(n.end.row)){var C=n.clone();C.start.row=C.end.row,C.start.column=0,this.drawBidiSingleLineMarker(l,C,i+" ace_br12",o,null,s)}else{$=this.$getTop(n.end.row,o);var y=n.end.column*o.characterWidth;this.elt(i+" ace_br12","height:"+p+"px;width:"+y+"px;top:"+$+"px;left:"+c+"px;"+(s||""))}if(p=(n.end.row-n.start.row-1)*o.lineHeight,!(p<=0)){$=this.$getTop(n.start.row+1,o);var _=(n.start.column?1:0)|(n.end.column?0:8);this.elt(i+(_?" ace_br"+_:""),"height:"+p+"px;right:0;top:"+$+"px;left:"+c+"px;"+(s||""))}},f.prototype.drawSingleLineMarker=function(l,n,i,o,s,c){if(this.session.$bidiHandler.isBidiRow(n.start.row))return this.drawBidiSingleLineMarker(l,n,i,o,s,c);var p=o.lineHeight,$=(n.end.column+(s||0)-n.start.column)*o.characterWidth,v=this.$getTop(n.start.row,o),C=this.$padding+n.start.column*o.characterWidth;this.elt(i,"height:"+p+"px;width:"+$+"px;top:"+v+"px;left:"+C+"px;"+(c||""))},f.prototype.drawBidiSingleLineMarker=function(l,n,i,o,s,c){var p=o.lineHeight,$=this.$getTop(n.start.row,o),v=this.$padding,C=this.session.$bidiHandler.getSelections(n.start.column,n.end.column);C.forEach(function(y){this.elt(i,"height:"+p+"px;width:"+(y.width+(s||0))+"px;top:"+$+"px;left:"+(v+y.left)+"px;"+(c||""))},this)},f.prototype.drawFullLineMarker=function(l,n,i,o,s){var c=this.$getTop(n.start.row,o),p=o.lineHeight;n.start.row!=n.end.row&&(p+=this.$getTop(n.end.row,o)-c),this.elt(i,"height:"+p+"px;top:"+c+"px;left:0;right:0;"+(s||""))},f.prototype.drawScreenLineMarker=function(l,n,i,o,s){var c=this.$getTop(n.start.row,o),p=o.lineHeight;this.elt(i,"height:"+p+"px;top:"+c+"px;left:0;right:0;"+(s||""))},f}();u.prototype.$padding=0;function r(f,l,n,i){return(f?1:0)|(l?2:0)|(n?4:0)|(i?8:0)}h.Marker=u}),ace.define("ace/layer/text_util",["require","exports","module"],function(e,h,m){var g=new Set(["text","rparen","lparen"]);h.isTextToken=function(a){return g.has(a)}}),ace.define("ace/layer/text",["require","exports","module","ace/lib/oop","ace/lib/dom","ace/lib/lang","ace/layer/lines","ace/lib/event_emitter","ace/config","ace/layer/text_util"],function(e,h,m){var g=e("../lib/oop"),a=e("../lib/dom"),u=e("../lib/lang"),r=e("./lines").Lines,f=e("../lib/event_emitter").EventEmitter,l=e("../config").nls,n=e("./text_util").isTextToken,i=function(){function o(s){this.dom=a,this.element=this.dom.createElement("div"),this.element.className="ace_layer ace_text-layer",s.appendChild(this.element),this.$updateEolChar=this.$updateEolChar.bind(this),this.$lines=new r(this.element)}return o.prototype.$updateEolChar=function(){var s=this.session.doc,c=s.getNewLineCharacter()==` +`&&s.getNewLineMode()!="windows",p=c?this.EOL_CHAR_LF:this.EOL_CHAR_CRLF;if(this.EOL_CHAR!=p)return this.EOL_CHAR=p,!0},o.prototype.setPadding=function(s){this.$padding=s,this.element.style.margin="0 "+s+"px"},o.prototype.getLineHeight=function(){return this.$fontMetrics.$characterSize.height||0},o.prototype.getCharacterWidth=function(){return this.$fontMetrics.$characterSize.width||0},o.prototype.$setFontMetrics=function(s){this.$fontMetrics=s,this.$fontMetrics.on("changeCharacterSize",function(c){this._signal("changeCharacterSize",c)}.bind(this)),this.$pollSizeChanges()},o.prototype.checkForSizeChanges=function(){this.$fontMetrics.checkForSizeChanges()},o.prototype.$pollSizeChanges=function(){return this.$pollSizeChangesTimer=this.$fontMetrics.$pollSizeChanges()},o.prototype.setSession=function(s){this.session=s,s&&this.$computeTabString()},o.prototype.setShowInvisibles=function(s){return this.showInvisibles==s?!1:(this.showInvisibles=s,typeof s=="string"?(this.showSpaces=/tab/i.test(s),this.showTabs=/space/i.test(s),this.showEOL=/eol/i.test(s)):this.showSpaces=this.showTabs=this.showEOL=s,this.$computeTabString(),!0)},o.prototype.setDisplayIndentGuides=function(s){return this.displayIndentGuides==s?!1:(this.displayIndentGuides=s,this.$computeTabString(),!0)},o.prototype.setHighlightIndentGuides=function(s){return this.$highlightIndentGuides===s?!1:(this.$highlightIndentGuides=s,s)},o.prototype.$computeTabString=function(){var s=this.session.getTabSize();this.tabSize=s;for(var c=this.$tabStrings=[0],p=1;px&&(b=E.end.row+1,E=this.session.getNextFoldLine(b,E),x=E?E.start.row:1/0),!(b>v);){var O=C[y++];if(O){this.dom.removeChildren(O),this.$renderLine(O,b,b==x?E:!1),_&&(O.style.top=this.$lines.computeLineTop(b,s,this.session)+"px");var M=s.lineHeight*this.session.getRowLength(b)+"px";O.style.height!=M&&(_=!0,O.style.height=M)}b++}if(_)for(;y0;v--)this.$lines.shift();if(c.lastRow>s.lastRow)for(var v=this.session.getFoldedRowCount(s.lastRow+1,c.lastRow);v>0;v--)this.$lines.pop();s.firstRowc.lastRow&&this.$lines.push(this.$renderLinesFragment(s,c.lastRow+1,s.lastRow)),this.$highlightIndentGuide()},o.prototype.$renderLinesFragment=function(s,c,p){for(var $=[],v=c,C=this.session.getNextFoldLine(v),y=C?C.start.row:1/0;v>y&&(v=C.end.row+1,C=this.session.getNextFoldLine(v,C),y=C?C.start.row:1/0),!(v>p);){var _=this.$lines.createCell(v,s,this.session),b=_.element;this.dom.removeChildren(b),a.setStyle(b.style,"height",this.$lines.computeLineHeight(v,s,this.session)+"px"),a.setStyle(b.style,"top",this.$lines.computeLineTop(v,s,this.session)+"px"),this.$renderLine(b,v,v==y?C:!1),this.$useLineGroups()?b.className="ace_line_group":b.className="ace_line",$.push(_),v++}return $},o.prototype.update=function(s){this.$lines.moveContainer(s),this.config=s;for(var c=s.firstRow,p=s.lastRow,$=this.$lines;$.getLength();)$.pop();$.push(this.$renderLinesFragment(s,c,p))},o.prototype.$renderToken=function(s,c,p,$){for(var v=this,C=/(\t)|( +)|([\x00-\x1f\x80-\xa0\xad\u1680\u180E\u2000-\u200f\u2028\u2029\u202F\u205F\uFEFF\uFFF9-\uFFFC\u2066\u2067\u2068\u202A\u202B\u202D\u202E\u202C\u2069]+)|(\u3000)|([\u1100-\u115F\u11A3-\u11A7\u11FA-\u11FF\u2329-\u232A\u2E80-\u2E99\u2E9B-\u2EF3\u2F00-\u2FD5\u2FF0-\u2FFB\u3001-\u303E\u3041-\u3096\u3099-\u30FF\u3105-\u312D\u3131-\u318E\u3190-\u31BA\u31C0-\u31E3\u31F0-\u321E\u3220-\u3247\u3250-\u32FE\u3300-\u4DBF\u4E00-\uA48C\uA490-\uA4C6\uA960-\uA97C\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFAFF\uFE10-\uFE19\uFE30-\uFE52\uFE54-\uFE66\uFE68-\uFE6B\uFF01-\uFF60\uFFE0-\uFFE6]|[\uD800-\uDBFF][\uDC00-\uDFFF])/g,y=this.dom.createFragment(this.element),_,b=0;_=C.exec($);){var E=_[1],x=_[2],O=_[3],M=_[4],k=_[5];if(!(!v.showSpaces&&x)){var T=b!=_.index?$.slice(b,_.index):"";if(b=_.index+_[0].length,T&&y.appendChild(this.dom.createTextNode(T,this.element)),E){var S=v.session.getScreenTabSize(c+_.index);y.appendChild(v.$tabStrings[S].cloneNode(!0)),c+=S-1}else if(x)if(v.showSpaces){var w=this.dom.createElement("span");w.className="ace_invisible ace_invisible_space",w.textContent=u.stringRepeat(v.SPACE_CHAR,x.length),y.appendChild(w)}else y.appendChild(this.dom.createTextNode(x,this.element));else if(O){var w=this.dom.createElement("span");w.className="ace_invisible ace_invisible_space ace_invalid",w.textContent=u.stringRepeat(v.SPACE_CHAR,O.length),y.appendChild(w)}else if(M){c+=1;var w=this.dom.createElement("span");w.style.width=v.config.characterWidth*2+"px",w.className=v.showSpaces?"ace_cjk ace_invisible ace_invisible_space":"ace_cjk",w.textContent=v.showSpaces?v.SPACE_CHAR:M,y.appendChild(w)}else if(k){c+=1;var w=this.dom.createElement("span");w.style.width=v.config.characterWidth*2+"px",w.className="ace_cjk",w.textContent=k,y.appendChild(w)}}}if(y.appendChild(this.dom.createTextNode(b?$.slice(b):$,this.element)),n(p.type))s.appendChild(y);else{var L="ace_"+p.type.replace(/\./g," ace_"),w=this.dom.createElement("span");p.type=="fold"&&(w.style.width=p.value.length*this.config.characterWidth+"px",w.setAttribute("title",l("Unfold code"))),w.className=L,w.appendChild(y),s.appendChild(w)}return c+$.length},o.prototype.renderIndentGuide=function(s,c,p){var $=c.search(this.$indentGuideRe);if($<=0||$>=p)return c;if(c[0]==" "){$-=$%this.tabSize;for(var v=$/this.tabSize,C=0;CC[y].start.row?this.$highlightIndentGuideMarker.dir=-1:this.$highlightIndentGuideMarker.dir=1;break}}if(!this.$highlightIndentGuideMarker.end&&s[c.row]!==""&&c.column===s[c.row].length){this.$highlightIndentGuideMarker.dir=1;for(var y=c.row+1;y0){for(var v=0;v<$.length;v++)if($[v].classList&&$[v].classList.contains("ace_indent-guide-active")){$[v].classList.remove("ace_indent-guide-active");break}}}},o.prototype.$setIndentGuideActive=function(s,c){var p=this.session.doc.getLine(s.row);if(p!==""){var $=s.element.childNodes;if($){var v=$[c-1];v&&v.classList&&v.classList.contains("ace_indent-guide")&&v.classList.add("ace_indent-guide-active")}}},o.prototype.$renderHighlightIndentGuide=function(){if(!!this.$lines){var s=this.$lines.cells;this.$clearActiveIndentGuide();var c=this.$highlightIndentGuideMarker.indentLevel;if(c!==0)if(this.$highlightIndentGuideMarker.dir===1)for(var p=0;p=this.$highlightIndentGuideMarker.start+1){if($.row>=this.$highlightIndentGuideMarker.end)break;this.$setIndentGuideActive($,c)}}else for(var p=s.length-1;p>=0;p--){var $=s[p];if(this.$highlightIndentGuideMarker.end&&$.row=C;)y=this.$renderToken(_,y,E,x.substring(0,C-$)),x=x.substring(C-$),$=C,_=this.$createLineElement(),s.appendChild(_),_.appendChild(this.dom.createTextNode(u.stringRepeat("\xA0",p.indent),this.element)),v++,y=0,C=p[v]||Number.MAX_VALUE;x.length!=0&&($+=x.length,y=this.$renderToken(_,y,E,x))}}p[p.length-1]>this.MAX_LINE_LENGTH&&this.$renderOverflowMessage(_,y,null,"",!0)},o.prototype.$renderSimpleLine=function(s,c){for(var p=0,$=0;$this.MAX_LINE_LENGTH)return this.$renderOverflowMessage(s,p,v,C);p=this.$renderToken(s,p,v,C)}}},o.prototype.$renderOverflowMessage=function(s,c,p,$,v){p&&this.$renderToken(s,c,p,$.slice(0,this.MAX_LINE_LENGTH-c));var C=this.dom.createElement("span");C.className="ace_inline_button ace_keyword ace_toggle_wrap",C.textContent=v?"":"",s.appendChild(C)},o.prototype.$renderLine=function(s,c,p){if(!p&&p!=!1&&(p=this.session.getFoldLine(c)),p)var $=this.$getFoldLineTokens(c,p);else var $=this.session.getTokens(c);var v=s;if($.length){var C=this.session.getRowSplitData(c);if(C&&C.length){this.$renderWrappedLine(s,$,C);var v=s.lastChild}else{var v=s;this.$useLineGroups()&&(v=this.$createLineElement(),s.appendChild(v)),this.$renderSimpleLine(v,$)}}else this.$useLineGroups()&&(v=this.$createLineElement(),s.appendChild(v));if(this.showEOL&&v){p&&(c=p.end.row);var y=this.dom.createElement("span");y.className="ace_invisible ace_invisible_eol",y.textContent=c==this.session.getLength()-1?this.EOF_CHAR:this.EOL_CHAR,v.appendChild(y)}},o.prototype.$getFoldLineTokens=function(s,c){var p=this.session,$=[];function v(y,_,b){for(var E=0,x=0;x+y[E].value.length<_;)if(x+=y[E].value.length,E++,E==y.length)return;if(x!=_){var O=y[E].value.substring(_-x);O.length>b-_&&(O=O.substring(0,b-_)),$.push({type:y[E].type,value:O}),x=_+O.length,E+=1}for(;xb?$.push({type:y[E].type,value:O.substring(0,b-x)}):$.push(y[E]),x+=O.length,E+=1}}var C=p.getTokens(s);return c.walk(function(y,_,b,E,x){y!=null?$.push({type:"fold",value:y}):(x&&(C=p.getTokens(_)),C.length&&v(C,E,b))},c.end.row,this.session.getLine(c.end.row).length),$},o.prototype.$useLineGroups=function(){return this.session.getUseWrapMode()},o}();i.prototype.EOF_CHAR="\xB6",i.prototype.EOL_CHAR_LF="\xAC",i.prototype.EOL_CHAR_CRLF="\xA4",i.prototype.EOL_CHAR=i.prototype.EOL_CHAR_LF,i.prototype.TAB_CHAR="\u2014",i.prototype.SPACE_CHAR="\xB7",i.prototype.$padding=0,i.prototype.MAX_LINE_LENGTH=1e4,i.prototype.showInvisibles=!1,i.prototype.showSpaces=!1,i.prototype.showTabs=!1,i.prototype.showEOL=!1,i.prototype.displayIndentGuides=!0,i.prototype.$highlightIndentGuides=!0,i.prototype.$tabStrings=[],i.prototype.destroy={},i.prototype.onChangeTabSize=i.prototype.$computeTabString,g.implement(i.prototype,f),h.Text=i}),ace.define("ace/layer/cursor",["require","exports","module","ace/lib/dom"],function(e,h,m){var g=e("../lib/dom"),a=function(){function u(r){this.element=g.createElement("div"),this.element.className="ace_layer ace_cursor-layer",r.appendChild(this.element),this.isVisible=!1,this.isBlinking=!0,this.blinkInterval=1e3,this.smoothBlinking=!1,this.cursors=[],this.cursor=this.addCursor(),g.addCssClass(this.element,"ace_hidden-cursors"),this.$updateCursors=this.$updateOpacity.bind(this)}return u.prototype.$updateOpacity=function(r){for(var f=this.cursors,l=f.length;l--;)g.setStyle(f[l].style,"opacity",r?"":"0")},u.prototype.$startCssAnimation=function(){for(var r=this.cursors,f=r.length;f--;)r[f].style.animationDuration=this.blinkInterval+"ms";this.$isAnimating=!0,setTimeout(function(){this.$isAnimating&&g.addCssClass(this.element,"ace_animate-blinking")}.bind(this))},u.prototype.$stopCssAnimation=function(){this.$isAnimating=!1,g.removeCssClass(this.element,"ace_animate-blinking")},u.prototype.setPadding=function(r){this.$padding=r},u.prototype.setSession=function(r){this.session=r},u.prototype.setBlinking=function(r){r!=this.isBlinking&&(this.isBlinking=r,this.restartTimer())},u.prototype.setBlinkInterval=function(r){r!=this.blinkInterval&&(this.blinkInterval=r,this.restartTimer())},u.prototype.setSmoothBlinking=function(r){r!=this.smoothBlinking&&(this.smoothBlinking=r,g.setCssClass(this.element,"ace_smooth-blinking",r),this.$updateCursors(!0),this.restartTimer())},u.prototype.addCursor=function(){var r=g.createElement("div");return r.className="ace_cursor",this.element.appendChild(r),this.cursors.push(r),r},u.prototype.removeCursor=function(){if(this.cursors.length>1){var r=this.cursors.pop();return r.parentNode.removeChild(r),r}},u.prototype.hideCursor=function(){this.isVisible=!1,g.addCssClass(this.element,"ace_hidden-cursors"),this.restartTimer()},u.prototype.showCursor=function(){this.isVisible=!0,g.removeCssClass(this.element,"ace_hidden-cursors"),this.restartTimer()},u.prototype.restartTimer=function(){var r=this.$updateCursors;if(clearInterval(this.intervalId),clearTimeout(this.timeoutId),this.$stopCssAnimation(),this.smoothBlinking&&(this.$isSmoothBlinking=!1,g.removeCssClass(this.element,"ace_smooth-blinking")),r(!0),!this.isBlinking||!this.blinkInterval||!this.isVisible){this.$stopCssAnimation();return}if(this.smoothBlinking&&(this.$isSmoothBlinking=!0,setTimeout(function(){this.$isSmoothBlinking&&g.addCssClass(this.element,"ace_smooth-blinking")}.bind(this))),g.HAS_CSS_ANIMATION)this.$startCssAnimation();else{var f=function(){this.timeoutId=setTimeout(function(){r(!1)},.6*this.blinkInterval)}.bind(this);this.intervalId=setInterval(function(){r(!0),f()},this.blinkInterval),f()}},u.prototype.getPixelPosition=function(r,f){if(!this.config||!this.session)return{left:0,top:0};r||(r=this.session.selection.getCursor());var l=this.session.documentToScreenPosition(r),n=this.$padding+(this.session.$bidiHandler.isBidiRow(l.row,r.row)?this.session.$bidiHandler.getPosLeft(l.column):l.column*this.config.characterWidth),i=(l.row-(f?this.config.firstRowScreen:0))*this.config.lineHeight;return{left:n,top:i}},u.prototype.isCursorInView=function(r,f){return r.top>=0&&r.topr.height+r.offset||o.top<0)&&l>1)){var s=this.cursors[n++]||this.addCursor(),c=s.style;this.drawCursor?this.drawCursor(s,o,r,f[l],this.session):this.isCursorInView(o,r)?(g.setStyle(c,"display","block"),g.translate(s,o.left,o.top),g.setStyle(c,"width",Math.round(r.characterWidth)+"px"),g.setStyle(c,"height",r.lineHeight+"px")):g.setStyle(c,"display","none")}}for(;this.cursors.length>n;)this.removeCursor();var p=this.session.getOverwrite();this.$setOverwrite(p),this.$pixelPos=o,this.restartTimer()},u.prototype.$setOverwrite=function(r){r!=this.overwrite&&(this.overwrite=r,r?g.addCssClass(this.element,"ace_overwrite-cursors"):g.removeCssClass(this.element,"ace_overwrite-cursors"))},u.prototype.destroy=function(){clearInterval(this.intervalId),clearTimeout(this.timeoutId)},u}();a.prototype.$padding=0,a.prototype.drawCursor=null,h.Cursor=a}),ace.define("ace/scrollbar",["require","exports","module","ace/lib/oop","ace/lib/dom","ace/lib/event","ace/lib/event_emitter"],function(e,h,m){var g=this&&this.__extends||function(){var s=function(c,p){return s=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function($,v){$.__proto__=v}||function($,v){for(var C in v)Object.prototype.hasOwnProperty.call(v,C)&&($[C]=v[C])},s(c,p)};return function(c,p){if(typeof p!="function"&&p!==null)throw new TypeError("Class extends value "+String(p)+" is not a constructor or null");s(c,p);function $(){this.constructor=c}c.prototype=p===null?Object.create(p):($.prototype=p.prototype,new $)}}(),a=e("./lib/oop"),u=e("./lib/dom"),r=e("./lib/event"),f=e("./lib/event_emitter").EventEmitter,l=32768,n=function(){function s(c,p){this.element=u.createElement("div"),this.element.className="ace_scrollbar ace_scrollbar"+p,this.inner=u.createElement("div"),this.inner.className="ace_scrollbar-inner",this.inner.textContent="\xA0",this.element.appendChild(this.inner),c.appendChild(this.element),this.setVisible(!1),this.skipEvent=!1,r.addListener(this.element,"scroll",this.onScroll.bind(this)),r.addListener(this.element,"mousedown",r.preventDefault)}return s.prototype.setVisible=function(c){this.element.style.display=c?"":"none",this.isVisible=c,this.coeff=1},s}();a.implement(n.prototype,f);var i=function(s){g(c,s);function c(p,$){var v=s.call(this,p,"-v")||this;return v.scrollTop=0,v.scrollHeight=0,$.$scrollbarWidth=v.width=u.scrollbarWidth(p.ownerDocument),v.inner.style.width=v.element.style.width=(v.width||15)+5+"px",v.$minWidth=0,v}return c.prototype.onScroll=function(){if(!this.skipEvent){if(this.scrollTop=this.element.scrollTop,this.coeff!=1){var p=this.element.clientHeight/this.scrollHeight;this.scrollTop=this.scrollTop*(1-p)/(this.coeff-p)}this._emit("scroll",{data:this.scrollTop})}this.skipEvent=!1},c.prototype.getWidth=function(){return Math.max(this.isVisible?this.width:0,this.$minWidth||0)},c.prototype.setHeight=function(p){this.element.style.height=p+"px"},c.prototype.setScrollHeight=function(p){this.scrollHeight=p,p>l?(this.coeff=l/p,p=l):this.coeff!=1&&(this.coeff=1),this.inner.style.height=p+"px"},c.prototype.setScrollTop=function(p){this.scrollTop!=p&&(this.skipEvent=!0,this.scrollTop=p,this.element.scrollTop=p*this.coeff)},c}(n);i.prototype.setInnerHeight=i.prototype.setScrollHeight;var o=function(s){g(c,s);function c(p,$){var v=s.call(this,p,"-h")||this;return v.scrollLeft=0,v.height=$.$scrollbarWidth,v.inner.style.height=v.element.style.height=(v.height||15)+5+"px",v}return c.prototype.onScroll=function(){this.skipEvent||(this.scrollLeft=this.element.scrollLeft,this._emit("scroll",{data:this.scrollLeft})),this.skipEvent=!1},c.prototype.getHeight=function(){return this.isVisible?this.height:0},c.prototype.setWidth=function(p){this.element.style.width=p+"px"},c.prototype.setInnerWidth=function(p){this.inner.style.width=p+"px"},c.prototype.setScrollWidth=function(p){this.inner.style.width=p+"px"},c.prototype.setScrollLeft=function(p){this.scrollLeft!=p&&(this.skipEvent=!0,this.scrollLeft=this.element.scrollLeft=p)},c}(n);h.ScrollBar=i,h.ScrollBarV=i,h.ScrollBarH=o,h.VScrollBar=i,h.HScrollBar=o}),ace.define("ace/scrollbar_custom",["require","exports","module","ace/lib/oop","ace/lib/dom","ace/lib/event","ace/lib/event_emitter"],function(e,h,m){var g=this&&this.__extends||function(){var o=function(s,c){return o=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(p,$){p.__proto__=$}||function(p,$){for(var v in $)Object.prototype.hasOwnProperty.call($,v)&&(p[v]=$[v])},o(s,c)};return function(s,c){if(typeof c!="function"&&c!==null)throw new TypeError("Class extends value "+String(c)+" is not a constructor or null");o(s,c);function p(){this.constructor=s}s.prototype=c===null?Object.create(c):(p.prototype=c.prototype,new p)}}(),a=e("./lib/oop"),u=e("./lib/dom"),r=e("./lib/event"),f=e("./lib/event_emitter").EventEmitter;u.importCssString(`.ace_editor>.ace_sb-v div, .ace_editor>.ace_sb-h div{ + position: absolute; + background: rgba(128, 128, 128, 0.6); + -moz-box-sizing: border-box; + box-sizing: border-box; + border: 1px solid #bbb; + border-radius: 2px; + z-index: 8; +} +.ace_editor>.ace_sb-v, .ace_editor>.ace_sb-h { + position: absolute; + z-index: 6; + background: none; + overflow: hidden!important; +} +.ace_editor>.ace_sb-v { + z-index: 6; + right: 0; + top: 0; + width: 12px; +} +.ace_editor>.ace_sb-v div { + z-index: 8; + right: 0; + width: 100%; +} +.ace_editor>.ace_sb-h { + bottom: 0; + left: 0; + height: 12px; +} +.ace_editor>.ace_sb-h div { + bottom: 0; + height: 100%; +} +.ace_editor>.ace_sb_grabbed { + z-index: 8; + background: #000; +}`,"ace_scrollbar.css",!1);var l=function(){function o(s,c){this.element=u.createElement("div"),this.element.className="ace_sb"+c,this.inner=u.createElement("div"),this.inner.className="",this.element.appendChild(this.inner),this.VScrollWidth=12,this.HScrollHeight=12,s.appendChild(this.element),this.setVisible(!1),this.skipEvent=!1,r.addMultiMouseDownListener(this.element,[500,300,300],this,"onMouseDown")}return o.prototype.setVisible=function(s){this.element.style.display=s?"":"none",this.isVisible=s,this.coeff=1},o}();a.implement(l.prototype,f);var n=function(o){g(s,o);function s(c,p){var $=o.call(this,c,"-v")||this;return $.scrollTop=0,$.scrollHeight=0,$.parent=c,$.width=$.VScrollWidth,$.renderer=p,$.inner.style.width=$.element.style.width=($.width||15)+"px",$.$minWidth=0,$}return s.prototype.onMouseDown=function(c,p){if(c==="mousedown"&&!(r.getButton(p)!==0||p.detail===2)){if(p.target===this.inner){var $=this,v=p.clientY,C=function(M){v=M.clientY},y=function(){clearInterval(x)},_=p.clientY,b=this.thumbTop,E=function(){if(v!==void 0){var M=$.scrollTopFromThumbTop(b+v-_);M!==$.scrollTop&&$._emit("scroll",{data:M})}};r.capture(this.inner,C,y);var x=setInterval(E,20);return r.preventDefault(p)}var O=p.clientY-this.element.getBoundingClientRect().top-this.thumbHeight/2;return this._emit("scroll",{data:this.scrollTopFromThumbTop(O)}),r.preventDefault(p)}},s.prototype.getHeight=function(){return this.height},s.prototype.scrollTopFromThumbTop=function(c){var p=c*(this.pageHeight-this.viewHeight)/(this.slideHeight-this.thumbHeight);return p=p>>0,p<0?p=0:p>this.pageHeight-this.viewHeight&&(p=this.pageHeight-this.viewHeight),p},s.prototype.getWidth=function(){return Math.max(this.isVisible?this.width:0,this.$minWidth||0)},s.prototype.setHeight=function(c){this.height=Math.max(0,c),this.slideHeight=this.height,this.viewHeight=this.height,this.setScrollHeight(this.pageHeight,!0)},s.prototype.setScrollHeight=function(c,p){this.pageHeight===c&&!p||(this.pageHeight=c,this.thumbHeight=this.slideHeight*this.viewHeight/this.pageHeight,this.thumbHeight>this.slideHeight&&(this.thumbHeight=this.slideHeight),this.thumbHeight<15&&(this.thumbHeight=15),this.inner.style.height=this.thumbHeight+"px",this.scrollTop>this.pageHeight-this.viewHeight&&(this.scrollTop=this.pageHeight-this.viewHeight,this.scrollTop<0&&(this.scrollTop=0),this._emit("scroll",{data:this.scrollTop})))},s.prototype.setScrollTop=function(c){this.scrollTop=c,c<0&&(c=0),this.thumbTop=c*(this.slideHeight-this.thumbHeight)/(this.pageHeight-this.viewHeight),this.inner.style.top=this.thumbTop+"px"},s}(l);n.prototype.setInnerHeight=n.prototype.setScrollHeight;var i=function(o){g(s,o);function s(c,p){var $=o.call(this,c,"-h")||this;return $.scrollLeft=0,$.scrollWidth=0,$.height=$.HScrollHeight,$.inner.style.height=$.element.style.height=($.height||12)+"px",$.renderer=p,$}return s.prototype.onMouseDown=function(c,p){if(c==="mousedown"&&!(r.getButton(p)!==0||p.detail===2)){if(p.target===this.inner){var $=this,v=p.clientX,C=function(M){v=M.clientX},y=function(){clearInterval(x)},_=p.clientX,b=this.thumbLeft,E=function(){if(v!==void 0){var M=$.scrollLeftFromThumbLeft(b+v-_);M!==$.scrollLeft&&$._emit("scroll",{data:M})}};r.capture(this.inner,C,y);var x=setInterval(E,20);return r.preventDefault(p)}var O=p.clientX-this.element.getBoundingClientRect().left-this.thumbWidth/2;return this._emit("scroll",{data:this.scrollLeftFromThumbLeft(O)}),r.preventDefault(p)}},s.prototype.getHeight=function(){return this.isVisible?this.height:0},s.prototype.scrollLeftFromThumbLeft=function(c){var p=c*(this.pageWidth-this.viewWidth)/(this.slideWidth-this.thumbWidth);return p=p>>0,p<0?p=0:p>this.pageWidth-this.viewWidth&&(p=this.pageWidth-this.viewWidth),p},s.prototype.setWidth=function(c){this.width=Math.max(0,c),this.element.style.width=this.width+"px",this.slideWidth=this.width,this.viewWidth=this.width,this.setScrollWidth(this.pageWidth,!0)},s.prototype.setScrollWidth=function(c,p){this.pageWidth===c&&!p||(this.pageWidth=c,this.thumbWidth=this.slideWidth*this.viewWidth/this.pageWidth,this.thumbWidth>this.slideWidth&&(this.thumbWidth=this.slideWidth),this.thumbWidth<15&&(this.thumbWidth=15),this.inner.style.width=this.thumbWidth+"px",this.scrollLeft>this.pageWidth-this.viewWidth&&(this.scrollLeft=this.pageWidth-this.viewWidth,this.scrollLeft<0&&(this.scrollLeft=0),this._emit("scroll",{data:this.scrollLeft})))},s.prototype.setScrollLeft=function(c){this.scrollLeft=c,c<0&&(c=0),this.thumbLeft=c*(this.slideWidth-this.thumbWidth)/(this.pageWidth-this.viewWidth),this.inner.style.left=this.thumbLeft+"px"},s}(l);i.prototype.setInnerWidth=i.prototype.setScrollWidth,h.ScrollBar=n,h.ScrollBarV=n,h.ScrollBarH=i,h.VScrollBar=n,h.HScrollBar=i}),ace.define("ace/renderloop",["require","exports","module","ace/lib/event"],function(e,h,m){var g=e("./lib/event"),a=function(){function u(r,f){this.onRender=r,this.pending=!1,this.changes=0,this.$recursionLimit=2,this.window=f||window;var l=this;this._flush=function(n){l.pending=!1;var i=l.changes;if(i&&(g.blockIdle(100),l.changes=0,l.onRender(i)),l.changes){if(l.$recursionLimit--<0)return;l.schedule()}else l.$recursionLimit=2}}return u.prototype.schedule=function(r){this.changes=this.changes|r,this.changes&&!this.pending&&(g.nextFrame(this._flush),this.pending=!0)},u.prototype.clear=function(r){var f=this.changes;return this.changes=0,f},u}();h.RenderLoop=a}),ace.define("ace/layer/font_metrics",["require","exports","module","ace/lib/oop","ace/lib/dom","ace/lib/lang","ace/lib/event","ace/lib/useragent","ace/lib/event_emitter"],function(e,h,m){var g=e("../lib/oop"),a=e("../lib/dom"),u=e("../lib/lang"),r=e("../lib/event"),f=e("../lib/useragent"),l=e("../lib/event_emitter").EventEmitter,n=512,i=typeof ResizeObserver=="function",o=200,s=function(){function c(p){this.el=a.createElement("div"),this.$setMeasureNodeStyles(this.el.style,!0),this.$main=a.createElement("div"),this.$setMeasureNodeStyles(this.$main.style),this.$measureNode=a.createElement("div"),this.$setMeasureNodeStyles(this.$measureNode.style),this.el.appendChild(this.$main),this.el.appendChild(this.$measureNode),p.appendChild(this.el),this.$measureNode.textContent=u.stringRepeat("X",n),this.$characterSize={width:0,height:0},i?this.$addObserver():this.checkForSizeChanges()}return c.prototype.$setMeasureNodeStyles=function(p,$){p.width=p.height="auto",p.left=p.top="0px",p.visibility="hidden",p.position="absolute",p.whiteSpace="pre",f.isIE<8?p["font-family"]="inherit":p.font="inherit",p.overflow=$?"hidden":"visible"},c.prototype.checkForSizeChanges=function(p){if(p===void 0&&(p=this.$measureSizes()),p&&(this.$characterSize.width!==p.width||this.$characterSize.height!==p.height)){this.$measureNode.style.fontWeight="bold";var $=this.$measureSizes();this.$measureNode.style.fontWeight="",this.$characterSize=p,this.charSizes=Object.create(null),this.allowBoldFonts=$&&$.width===p.width&&$.height===p.height,this._emit("changeCharacterSize",{data:p})}},c.prototype.$addObserver=function(){var p=this;this.$observer=new window.ResizeObserver(function($){p.checkForSizeChanges()}),this.$observer.observe(this.$measureNode)},c.prototype.$pollSizeChanges=function(){if(this.$pollSizeChangesTimer||this.$observer)return this.$pollSizeChangesTimer;var p=this;return this.$pollSizeChangesTimer=r.onIdle(function $(){p.checkForSizeChanges(),r.onIdle($,500)},500)},c.prototype.setPolling=function(p){p?this.$pollSizeChanges():this.$pollSizeChangesTimer&&(clearInterval(this.$pollSizeChangesTimer),this.$pollSizeChangesTimer=0)},c.prototype.$measureSizes=function(p){var $={height:(p||this.$measureNode).clientHeight,width:(p||this.$measureNode).clientWidth/n};return $.width===0||$.height===0?null:$},c.prototype.$measureCharWidth=function(p){this.$main.textContent=u.stringRepeat(p,n);var $=this.$main.getBoundingClientRect();return $.width/n},c.prototype.getCharacterWidth=function(p){var $=this.charSizes[p];return $===void 0&&($=this.charSizes[p]=this.$measureCharWidth(p)/this.$characterSize.width),$},c.prototype.destroy=function(){clearInterval(this.$pollSizeChangesTimer),this.$observer&&this.$observer.disconnect(),this.el&&this.el.parentNode&&this.el.parentNode.removeChild(this.el)},c.prototype.$getZoom=function(p){return!p||!p.parentElement?1:(window.getComputedStyle(p).zoom||1)*this.$getZoom(p.parentElement)},c.prototype.$initTransformMeasureNodes=function(){var p=function($,v){return["div",{style:"position: absolute;top:"+$+"px;left:"+v+"px;"}]};this.els=a.buildDom([p(0,0),p(o,0),p(0,o),p(o,o)],this.el)},c.prototype.transformCoordinates=function(p,$){if(p){var v=this.$getZoom(this.el);p=b(1/v,p)}function C(V,R,B){var N=V[1]*R[0]-V[0]*R[1];return[(-R[1]*B[0]+R[0]*B[1])/N,(+V[1]*B[0]-V[0]*B[1])/N]}function y(V,R){return[V[0]-R[0],V[1]-R[1]]}function _(V,R){return[V[0]+R[0],V[1]+R[1]]}function b(V,R){return[V*R[0],V*R[1]]}this.els||this.$initTransformMeasureNodes();function E(V){var R=V.getBoundingClientRect();return[R.left,R.top]}var x=E(this.els[0]),O=E(this.els[1]),M=E(this.els[2]),k=E(this.els[3]),T=C(y(k,O),y(k,M),y(_(O,M),_(k,x))),S=b(1+T[0],y(O,x)),w=b(1+T[1],y(M,x));if($){var L=$,q=T[0]*L[0]/o+T[1]*L[1]/o+1,A=_(b(L[0],S),b(L[1],w));return _(b(1/q/o,A),x)}var I=y(p,x),F=C(y(S,b(T[0],I)),y(w,b(T[1],I)),I);return b(o,F)},c}();s.prototype.$characterSize={width:0,height:0},g.implement(s.prototype,l),h.FontMetrics=s}),ace.define("ace/css/editor-css",["require","exports","module"],function(e,h,m){m.exports=` +.ace_br1 {border-top-left-radius : 3px;} +.ace_br2 {border-top-right-radius : 3px;} +.ace_br3 {border-top-left-radius : 3px; border-top-right-radius: 3px;} +.ace_br4 {border-bottom-right-radius: 3px;} +.ace_br5 {border-top-left-radius : 3px; border-bottom-right-radius: 3px;} +.ace_br6 {border-top-right-radius : 3px; border-bottom-right-radius: 3px;} +.ace_br7 {border-top-left-radius : 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px;} +.ace_br8 {border-bottom-left-radius : 3px;} +.ace_br9 {border-top-left-radius : 3px; border-bottom-left-radius: 3px;} +.ace_br10{border-top-right-radius : 3px; border-bottom-left-radius: 3px;} +.ace_br11{border-top-left-radius : 3px; border-top-right-radius: 3px; border-bottom-left-radius: 3px;} +.ace_br12{border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;} +.ace_br13{border-top-left-radius : 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;} +.ace_br14{border-top-right-radius : 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;} +.ace_br15{border-top-left-radius : 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;} + + +.ace_editor { + position: relative; + overflow: hidden; + padding: 0; + font: 12px/normal 'Monaco', 'Menlo', 'Ubuntu Mono', 'Consolas', 'Source Code Pro', 'source-code-pro', monospace; + direction: ltr; + text-align: left; + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); +} + +.ace_scroller { + position: absolute; + overflow: hidden; + top: 0; + bottom: 0; + background-color: inherit; + -ms-user-select: none; + -moz-user-select: none; + -webkit-user-select: none; + user-select: none; + cursor: text; +} + +.ace_content { + position: absolute; + box-sizing: border-box; + min-width: 100%; + contain: style size layout; + font-variant-ligatures: no-common-ligatures; +} + +.ace_keyboard-focus:focus { + box-shadow: inset 0 0 0 2px #5E9ED6; + outline: none; +} + +.ace_dragging .ace_scroller:before{ + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + content: ''; + background: rgba(250, 250, 250, 0.01); + z-index: 1000; +} +.ace_dragging.ace_dark .ace_scroller:before{ + background: rgba(0, 0, 0, 0.01); +} + +.ace_gutter { + position: absolute; + overflow : hidden; + width: auto; + top: 0; + bottom: 0; + left: 0; + cursor: default; + z-index: 4; + -ms-user-select: none; + -moz-user-select: none; + -webkit-user-select: none; + user-select: none; + contain: style size layout; +} + +.ace_gutter-active-line { + position: absolute; + left: 0; + right: 0; +} + +.ace_scroller.ace_scroll-left:after { + content: ""; + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + box-shadow: 17px 0 16px -16px rgba(0, 0, 0, 0.4) inset; + pointer-events: none; +} + +.ace_gutter-cell, .ace_gutter-cell_svg-icons { + position: absolute; + top: 0; + left: 0; + right: 0; + padding-left: 19px; + padding-right: 6px; + background-repeat: no-repeat; +} + +.ace_gutter-cell_svg-icons .ace_gutter_annotation { + margin-left: -14px; + float: left; +} + +.ace_gutter-cell .ace_gutter_annotation { + margin-left: -19px; + float: left; +} + +.ace_gutter-cell.ace_error, .ace_icon.ace_error, .ace_icon.ace_error_fold { + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAABOFBMVEX/////////QRswFAb/Ui4wFAYwFAYwFAaWGAfDRymzOSH/PxswFAb/SiUwFAYwFAbUPRvjQiDllog5HhHdRybsTi3/Tyv9Tir+Syj/UC3////XurebMBIwFAb/RSHbPx/gUzfdwL3kzMivKBAwFAbbvbnhPx66NhowFAYwFAaZJg8wFAaxKBDZurf/RB6mMxb/SCMwFAYwFAbxQB3+RB4wFAb/Qhy4Oh+4QifbNRcwFAYwFAYwFAb/QRzdNhgwFAYwFAbav7v/Uy7oaE68MBK5LxLewr/r2NXewLswFAaxJw4wFAbkPRy2PyYwFAaxKhLm1tMwFAazPiQwFAaUGAb/QBrfOx3bvrv/VC/maE4wFAbRPBq6MRO8Qynew8Dp2tjfwb0wFAbx6eju5+by6uns4uH9/f36+vr/GkHjAAAAYnRSTlMAGt+64rnWu/bo8eAA4InH3+DwoN7j4eLi4xP99Nfg4+b+/u9B/eDs1MD1mO7+4PHg2MXa347g7vDizMLN4eG+Pv7i5evs/v79yu7S3/DV7/498Yv24eH+4ufQ3Ozu/v7+y13sRqwAAADLSURBVHjaZc/XDsFgGIBhtDrshlitmk2IrbHFqL2pvXf/+78DPokj7+Fz9qpU/9UXJIlhmPaTaQ6QPaz0mm+5gwkgovcV6GZzd5JtCQwgsxoHOvJO15kleRLAnMgHFIESUEPmawB9ngmelTtipwwfASilxOLyiV5UVUyVAfbG0cCPHig+GBkzAENHS0AstVF6bacZIOzgLmxsHbt2OecNgJC83JERmePUYq8ARGkJx6XtFsdddBQgZE2nPR6CICZhawjA4Fb/chv+399kfR+MMMDGOQAAAABJRU5ErkJggg=="); + background-repeat: no-repeat; + background-position: 2px center; +} + +.ace_gutter-cell.ace_warning, .ace_icon.ace_warning, .ace_icon.ace_warning_fold { + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAmVBMVEX///8AAAD///8AAAAAAABPSzb/5sAAAAB/blH/73z/ulkAAAAAAAD85pkAAAAAAAACAgP/vGz/rkDerGbGrV7/pkQICAf////e0IsAAAD/oED/qTvhrnUAAAD/yHD/njcAAADuv2r/nz//oTj/p064oGf/zHAAAAA9Nir/tFIAAAD/tlTiuWf/tkIAAACynXEAAAAAAAAtIRW7zBpBAAAAM3RSTlMAABR1m7RXO8Ln31Z36zT+neXe5OzooRDfn+TZ4p3h2hTf4t3k3ucyrN1K5+Xaks52Sfs9CXgrAAAAjklEQVR42o3PbQ+CIBQFYEwboPhSYgoYunIqqLn6/z8uYdH8Vmdnu9vz4WwXgN/xTPRD2+sgOcZjsge/whXZgUaYYvT8QnuJaUrjrHUQreGczuEafQCO/SJTufTbroWsPgsllVhq3wJEk2jUSzX3CUEDJC84707djRc5MTAQxoLgupWRwW6UB5fS++NV8AbOZgnsC7BpEAAAAABJRU5ErkJggg=="); + background-repeat: no-repeat; + background-position: 2px center; +} + +.ace_gutter-cell.ace_info, .ace_icon.ace_info { + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAAAAAA6mKC9AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAAJ0Uk5TAAB2k804AAAAPklEQVQY02NgIB68QuO3tiLznjAwpKTgNyDbMegwisCHZUETUZV0ZqOquBpXj2rtnpSJT1AEnnRmL2OgGgAAIKkRQap2htgAAAAASUVORK5CYII="); + background-repeat: no-repeat; + background-position: 2px center; +} +.ace_dark .ace_gutter-cell.ace_info, .ace_dark .ace_icon.ace_info { + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAJFBMVEUAAAChoaGAgIAqKiq+vr6tra1ZWVmUlJSbm5s8PDxubm56enrdgzg3AAAAAXRSTlMAQObYZgAAAClJREFUeNpjYMAPdsMYHegyJZFQBlsUlMFVCWUYKkAZMxZAGdxlDMQBAG+TBP4B6RyJAAAAAElFTkSuQmCC"); +} + +.ace_icon_svg.ace_error { + -webkit-mask-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMCAxNiI+CjxnIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlPSJyZWQiIHNoYXBlLXJlbmRlcmluZz0iZ2VvbWV0cmljUHJlY2lzaW9uIj4KPGNpcmNsZSBmaWxsPSJub25lIiBjeD0iOCIgY3k9IjgiIHI9IjciIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz4KPGxpbmUgeDE9IjExIiB5MT0iNSIgeDI9IjUiIHkyPSIxMSIvPgo8bGluZSB4MT0iMTEiIHkxPSIxMSIgeDI9IjUiIHkyPSI1Ii8+CjwvZz4KPC9zdmc+"); + background-color: crimson; +} +.ace_icon_svg.ace_warning { + -webkit-mask-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMCAxNiI+CjxnIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlPSJkYXJrb3JhbmdlIiBzaGFwZS1yZW5kZXJpbmc9Imdlb21ldHJpY1ByZWNpc2lvbiI+Cjxwb2x5Z29uIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGZpbGw9Im5vbmUiIHBvaW50cz0iOCAxIDE1IDE1IDEgMTUgOCAxIi8+CjxyZWN0IHg9IjgiIHk9IjEyIiB3aWR0aD0iMC4wMSIgaGVpZ2h0PSIwLjAxIi8+CjxsaW5lIHgxPSI4IiB5MT0iNiIgeDI9IjgiIHkyPSIxMCIvPgo8L2c+Cjwvc3ZnPg=="); + background-color: darkorange; +} +.ace_icon_svg.ace_info { + -webkit-mask-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMCAxNiI+CjxnIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlPSJibHVlIiBzaGFwZS1yZW5kZXJpbmc9Imdlb21ldHJpY1ByZWNpc2lvbiI+CjxjaXJjbGUgZmlsbD0ibm9uZSIgY3g9IjgiIGN5PSI4IiByPSI3IiBzdHJva2UtbGluZWpvaW49InJvdW5kIi8+Cjxwb2x5bGluZSBwb2ludHM9IjggMTEgOCA4Ii8+Cjxwb2x5bGluZSBwb2ludHM9IjkgOCA2IDgiLz4KPGxpbmUgeDE9IjEwIiB5MT0iMTEiIHgyPSI2IiB5Mj0iMTEiLz4KPHJlY3QgeD0iOCIgeT0iNSIgd2lkdGg9IjAuMDEiIGhlaWdodD0iMC4wMSIvPgo8L2c+Cjwvc3ZnPg=="); + background-color: royalblue; +} + +.ace_icon_svg.ace_error_fold { + -webkit-mask-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMCAxNiIgZmlsbD0ibm9uZSI+CiAgPHBhdGggZD0ibSAxOC45Mjk4NTEsNy44Mjk4MDc2IGMgMC4xNDYzNTMsNi4zMzc0NjA0IC02LjMyMzE0Nyw3Ljc3Nzg0NDQgLTcuNDc3OTEyLDcuNzc3ODQ0NCAtMi4xMDcyNzI2LC0wLjEyODc1IDUuMTE3Njc4LDAuMzU2MjQ5IDUuMDUxNjk4LC03Ljg3MDA2MTggLTAuNjA0NjcyLC04LjAwMzk3MzQ5IC03LjA3NzI3MDYsLTcuNTYzMTE4OSAtNC44NTczLC03LjQzMDM5NTU2IDEuNjA2LC0wLjExNTE0MjI1IDYuODk3NDg1LDEuMjYyNTQ1OTYgNy4yODM1MTQsNy41MjI2MTI5NiB6IiBmaWxsPSJjcmltc29uIiBzdHJva2Utd2lkdGg9IjIiLz4KICA8cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0ibSA4LjExNDc1NjIsMi4wNTI5ODI4IGMgMy4zNDkxNjk4LDAgNi4wNjQxMzI4LDIuNjc2ODYyNyA2LjA2NDEzMjgsNS45Nzg5NTMgMCwzLjMwMjExMjIgLTIuNzE0OTYzLDUuOTc4OTIwMiAtNi4wNjQxMzI4LDUuOTc4OTIwMiAtMy4zNDkxNDczLDAgLTYuMDY0MTc3MiwtMi42NzY4MDggLTYuMDY0MTc3MiwtNS45Nzg5MjAyIDAuMDA1MzksLTMuMjk5ODg2MSAyLjcxNzI2NTYsLTUuOTczNjQwOCA2LjA2NDE3NzIsLTUuOTc4OTUzIHogbSAwLC0xLjczNTgyNzE5IGMgLTQuMzIxNDgzNiwwIC03LjgyNDc0MDM4LDMuNDU0MDE4NDkgLTcuODI0NzQwMzgsNy43MTQ3ODAxOSAwLDQuMjYwNzI4MiAzLjUwMzI1Njc4LDcuNzE0NzQ1MiA3LjgyNDc0MDM4LDcuNzE0NzQ1MiA0LjMyMTQ0OTgsMCA3LjgyNDY5OTgsLTMuNDU0MDE3IDcuODI0Njk5OCwtNy43MTQ3NDUyIDAsLTIuMDQ2MDkxNCAtMC44MjQzOTIsLTQuMDA4MzY3MiAtMi4yOTE3NTYsLTUuNDU1MTc0NiBDIDEyLjE4MDIyNSwxLjEyOTk2NDggMTAuMTkwMDEzLDAuMzE3MTU1NjEgOC4xMTQ3NTYyLDAuMzE3MTU1NjEgWiBNIDYuOTM3NDU2Myw4LjI0MDU5ODUgNC42NzE4Njg1LDEwLjQ4NTg1MiA2LjAwODY4MTQsMTEuODc2NzI4IDguMzE3MDAzNSw5LjYwMDc5MTEgMTAuNjI1MzM3LDExLjg3NjcyOCAxMS45NjIxMzgsMTAuNDg1ODUyIDkuNjk2NTUwOCw4LjI0MDU5ODUgMTEuOTYyMTM4LDYuMDA2ODA2NiAxMC41NzMyNDYsNC42Mzc0MzM1IDguMzE3MDAzNSw2Ljg3MzQyOTcgNi4wNjA3NjA3LDQuNjM3NDMzNSA0LjY3MTg2ODUsNi4wMDY4MDY2IFoiIGZpbGw9ImNyaW1zb24iIHN0cm9rZS13aWR0aD0iMiIvPgo8L3N2Zz4="); + background-color: crimson; +} +.ace_icon_svg.ace_warning_fold { + -webkit-mask-image: url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjAiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAyMCAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xNC43NzY5IDE0LjczMzdMOC42NTE5MiAyLjQ4MzY5QzguMzI5NDYgMS44Mzg3NyA3LjQwOTEzIDEuODM4NzcgNy4wODY2NyAyLjQ4MzY5TDAuOTYxNjY5IDE0LjczMzdDMC42NzA3NzUgMTUuMzE1NSAxLjA5MzgzIDE2IDEuNzQ0MjkgMTZIMTMuOTk0M0MxNC42NDQ4IDE2IDE1LjA2NzggMTUuMzE1NSAxNC43NzY5IDE0LjczMzdaTTMuMTYwMDcgMTQuMjVMNy44NjkyOSA0LjgzMTU2TDEyLjU3ODUgMTQuMjVIMy4xNjAwN1pNOC43NDQyOSAxMS42MjVWMTMuMzc1SDYuOTk0MjlWMTEuNjI1SDguNzQ0MjlaTTYuOTk0MjkgMTAuNzVWNy4yNUg4Ljc0NDI5VjEwLjc1SDYuOTk0MjlaIiBmaWxsPSIjRUM3MjExIi8+CjxwYXRoIGQ9Ik0xMS4xOTkxIDIuOTUyMzhDMTAuODgwOSAyLjMxNDY3IDEwLjM1MzcgMS44MDUyNiA5LjcwNTUgMS41MDlMMTEuMDQxIDEuMDY5NzhDMTEuNjg4MyAwLjk0OTgxNCAxMi4zMzcgMS4yNzI2MyAxMi42MzE3IDEuODYxNDFMMTcuNjEzNiAxMS44MTYxQzE4LjM1MjcgMTMuMjkyOSAxNy41OTM4IDE1LjA4MDQgMTYuMDE4IDE1LjU3NDVDMTYuNDA0NCAxNC40NTA3IDE2LjMyMzEgMTMuMjE4OCAxNS43OTI0IDEyLjE1NTVMMTEuMTk5MSAyLjk1MjM4WiIgZmlsbD0iI0VDNzIxMSIvPgo8L3N2Zz4="); + background-color: darkorange; +} + +.ace_scrollbar { + contain: strict; + position: absolute; + right: 0; + bottom: 0; + z-index: 6; +} + +.ace_scrollbar-inner { + position: absolute; + cursor: text; + left: 0; + top: 0; +} + +.ace_scrollbar-v{ + overflow-x: hidden; + overflow-y: scroll; + top: 0; +} + +.ace_scrollbar-h { + overflow-x: scroll; + overflow-y: hidden; + left: 0; +} + +.ace_print-margin { + position: absolute; + height: 100%; +} + +.ace_text-input { + position: absolute; + z-index: 0; + width: 0.5em; + height: 1em; + opacity: 0; + background: transparent; + -moz-appearance: none; + appearance: none; + border: none; + resize: none; + outline: none; + overflow: hidden; + font: inherit; + padding: 0 1px; + margin: 0 -1px; + contain: strict; + -ms-user-select: text; + -moz-user-select: text; + -webkit-user-select: text; + user-select: text; + /*with \`pre-line\` chrome inserts   instead of space*/ + white-space: pre!important; +} +.ace_text-input.ace_composition { + background: transparent; + color: inherit; + z-index: 1000; + opacity: 1; +} +.ace_composition_placeholder { color: transparent } +.ace_composition_marker { + border-bottom: 1px solid; + position: absolute; + border-radius: 0; + margin-top: 1px; +} + +[ace_nocontext=true] { + transform: none!important; + filter: none!important; + clip-path: none!important; + mask : none!important; + contain: none!important; + perspective: none!important; + mix-blend-mode: initial!important; + z-index: auto; +} + +.ace_layer { + z-index: 1; + position: absolute; + overflow: hidden; + /* workaround for chrome bug https://github.com/ajaxorg/ace/issues/2312*/ + word-wrap: normal; + white-space: pre; + height: 100%; + width: 100%; + box-sizing: border-box; + /* setting pointer-events: auto; on node under the mouse, which changes + during scroll, will break mouse wheel scrolling in Safari */ + pointer-events: none; +} + +.ace_gutter-layer { + position: relative; + width: auto; + text-align: right; + pointer-events: auto; + height: 1000000px; + contain: style size layout; +} + +.ace_text-layer { + font: inherit !important; + position: absolute; + height: 1000000px; + width: 1000000px; + contain: style size layout; +} + +.ace_text-layer > .ace_line, .ace_text-layer > .ace_line_group { + contain: style size layout; + position: absolute; + top: 0; + left: 0; + right: 0; +} + +.ace_hidpi .ace_text-layer, +.ace_hidpi .ace_gutter-layer, +.ace_hidpi .ace_content, +.ace_hidpi .ace_gutter { + contain: strict; +} +.ace_hidpi .ace_text-layer > .ace_line, +.ace_hidpi .ace_text-layer > .ace_line_group { + contain: strict; +} + +.ace_cjk { + display: inline-block; + text-align: center; +} + +.ace_cursor-layer { + z-index: 4; +} + +.ace_cursor { + z-index: 4; + position: absolute; + box-sizing: border-box; + border-left: 2px solid; + /* workaround for smooth cursor repaintng whole screen in chrome */ + transform: translatez(0); +} + +.ace_multiselect .ace_cursor { + border-left-width: 1px; +} + +.ace_slim-cursors .ace_cursor { + border-left-width: 1px; +} + +.ace_overwrite-cursors .ace_cursor { + border-left-width: 0; + border-bottom: 1px solid; +} + +.ace_hidden-cursors .ace_cursor { + opacity: 0.2; +} + +.ace_hasPlaceholder .ace_hidden-cursors .ace_cursor { + opacity: 0; +} + +.ace_smooth-blinking .ace_cursor { + transition: opacity 0.18s; +} + +.ace_animate-blinking .ace_cursor { + animation-duration: 1000ms; + animation-timing-function: step-end; + animation-name: blink-ace-animate; + animation-iteration-count: infinite; +} + +.ace_animate-blinking.ace_smooth-blinking .ace_cursor { + animation-duration: 1000ms; + animation-timing-function: ease-in-out; + animation-name: blink-ace-animate-smooth; +} + +@keyframes blink-ace-animate { + from, to { opacity: 1; } + 60% { opacity: 0; } +} + +@keyframes blink-ace-animate-smooth { + from, to { opacity: 1; } + 45% { opacity: 1; } + 60% { opacity: 0; } + 85% { opacity: 0; } +} + +.ace_marker-layer .ace_step, .ace_marker-layer .ace_stack { + position: absolute; + z-index: 3; +} + +.ace_marker-layer .ace_selection { + position: absolute; + z-index: 5; +} + +.ace_marker-layer .ace_bracket { + position: absolute; + z-index: 6; +} + +.ace_marker-layer .ace_error_bracket { + position: absolute; + border-bottom: 1px solid #DE5555; + border-radius: 0; +} + +.ace_marker-layer .ace_active-line { + position: absolute; + z-index: 2; +} + +.ace_marker-layer .ace_selected-word { + position: absolute; + z-index: 4; + box-sizing: border-box; +} + +.ace_line .ace_fold { + box-sizing: border-box; + + display: inline-block; + height: 11px; + margin-top: -2px; + vertical-align: middle; + + background-image: + url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAJCAYAAADU6McMAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAJpJREFUeNpi/P//PwOlgAXGYGRklAVSokD8GmjwY1wasKljQpYACtpCFeADcHVQfQyMQAwzwAZI3wJKvCLkfKBaMSClBlR7BOQikCFGQEErIH0VqkabiGCAqwUadAzZJRxQr/0gwiXIal8zQQPnNVTgJ1TdawL0T5gBIP1MUJNhBv2HKoQHHjqNrA4WO4zY0glyNKLT2KIfIMAAQsdgGiXvgnYAAAAASUVORK5CYII="), + url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAA3CAYAAADNNiA5AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAACJJREFUeNpi+P//fxgTAwPDBxDxD078RSX+YeEyDFMCIMAAI3INmXiwf2YAAAAASUVORK5CYII="); + background-repeat: no-repeat, repeat-x; + background-position: center center, top left; + color: transparent; + + border: 1px solid black; + border-radius: 2px; + + cursor: pointer; + pointer-events: auto; +} + +.ace_dark .ace_fold { +} + +.ace_fold:hover{ + background-image: + url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAJCAYAAADU6McMAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAJpJREFUeNpi/P//PwOlgAXGYGRklAVSokD8GmjwY1wasKljQpYACtpCFeADcHVQfQyMQAwzwAZI3wJKvCLkfKBaMSClBlR7BOQikCFGQEErIH0VqkabiGCAqwUadAzZJRxQr/0gwiXIal8zQQPnNVTgJ1TdawL0T5gBIP1MUJNhBv2HKoQHHjqNrA4WO4zY0glyNKLT2KIfIMAAQsdgGiXvgnYAAAAASUVORK5CYII="), + url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAA3CAYAAADNNiA5AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAACBJREFUeNpi+P//fz4TAwPDZxDxD5X4i5fLMEwJgAADAEPVDbjNw87ZAAAAAElFTkSuQmCC"); +} + +.ace_tooltip { + background-color: #f5f5f5; + border: 1px solid gray; + border-radius: 1px; + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3); + color: black; + max-width: 100%; + padding: 3px 4px; + position: fixed; + z-index: 999999; + box-sizing: border-box; + cursor: default; + white-space: pre-wrap; + word-wrap: break-word; + line-height: normal; + font-style: normal; + font-weight: normal; + letter-spacing: normal; + pointer-events: none; + overflow: auto; + max-width: min(60em, 66vw); + overscroll-behavior: contain; +} +.ace_tooltip pre { + white-space: pre-wrap; +} + +.ace_tooltip.ace_dark { + background-color: #636363; + color: #fff; +} + +.ace_tooltip:focus { + outline: 1px solid #5E9ED6; +} + +.ace_icon { + display: inline-block; + width: 18px; + vertical-align: top; +} + +.ace_icon_svg { + display: inline-block; + width: 12px; + vertical-align: top; + -webkit-mask-repeat: no-repeat; + -webkit-mask-size: 12px; + -webkit-mask-position: center; +} + +.ace_folding-enabled > .ace_gutter-cell, .ace_folding-enabled > .ace_gutter-cell_svg-icons { + padding-right: 13px; +} + +.ace_fold-widget { + box-sizing: border-box; + + margin: 0 -12px 0 1px; + display: none; + width: 11px; + vertical-align: top; + + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAANElEQVR42mWKsQ0AMAzC8ixLlrzQjzmBiEjp0A6WwBCSPgKAXoLkqSot7nN3yMwR7pZ32NzpKkVoDBUxKAAAAABJRU5ErkJggg=="); + background-repeat: no-repeat; + background-position: center; + + border-radius: 3px; + + border: 1px solid transparent; + cursor: pointer; +} + +.ace_folding-enabled .ace_fold-widget { + display: inline-block; +} + +.ace_fold-widget.ace_end { + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAANElEQVR42m3HwQkAMAhD0YzsRchFKI7sAikeWkrxwScEB0nh5e7KTPWimZki4tYfVbX+MNl4pyZXejUO1QAAAABJRU5ErkJggg=="); +} + +.ace_fold-widget.ace_closed { + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAGCAYAAAAG5SQMAAAAOUlEQVR42jXKwQkAMAgDwKwqKD4EwQ26sSOkVWjgIIHAzPiCgaqiqnJHZnKICBERHN194O5b9vbLuAVRL+l0YWnZAAAAAElFTkSuQmCCXA=="); +} + +.ace_fold-widget:hover { + border: 1px solid rgba(0, 0, 0, 0.3); + background-color: rgba(255, 255, 255, 0.2); + box-shadow: 0 1px 1px rgba(255, 255, 255, 0.7); +} + +.ace_fold-widget:active { + border: 1px solid rgba(0, 0, 0, 0.4); + background-color: rgba(0, 0, 0, 0.05); + box-shadow: 0 1px 1px rgba(255, 255, 255, 0.8); +} +/** + * Dark version for fold widgets + */ +.ace_dark .ace_fold-widget { + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHklEQVQIW2P4//8/AzoGEQ7oGCaLLAhWiSwB146BAQCSTPYocqT0AAAAAElFTkSuQmCC"); +} +.ace_dark .ace_fold-widget.ace_end { + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAH0lEQVQIW2P4//8/AxQ7wNjIAjDMgC4AxjCVKBirIAAF0kz2rlhxpAAAAABJRU5ErkJggg=="); +} +.ace_dark .ace_fold-widget.ace_closed { + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAHElEQVQIW2P4//+/AxAzgDADlOOAznHAKgPWAwARji8UIDTfQQAAAABJRU5ErkJggg=="); +} +.ace_dark .ace_fold-widget:hover { + box-shadow: 0 1px 1px rgba(255, 255, 255, 0.2); + background-color: rgba(255, 255, 255, 0.1); +} +.ace_dark .ace_fold-widget:active { + box-shadow: 0 1px 1px rgba(255, 255, 255, 0.2); +} + +.ace_inline_button { + border: 1px solid lightgray; + display: inline-block; + margin: -1px 8px; + padding: 0 5px; + pointer-events: auto; + cursor: pointer; +} +.ace_inline_button:hover { + border-color: gray; + background: rgba(200,200,200,0.2); + display: inline-block; + pointer-events: auto; +} + +.ace_fold-widget.ace_invalid { + background-color: #FFB4B4; + border-color: #DE5555; +} + +.ace_fade-fold-widgets .ace_fold-widget { + transition: opacity 0.4s ease 0.05s; + opacity: 0; +} + +.ace_fade-fold-widgets:hover .ace_fold-widget { + transition: opacity 0.05s ease 0.05s; + opacity:1; +} + +.ace_underline { + text-decoration: underline; +} + +.ace_bold { + font-weight: bold; +} + +.ace_nobold .ace_bold { + font-weight: normal; +} + +.ace_italic { + font-style: italic; +} + + +.ace_error-marker { + background-color: rgba(255, 0, 0,0.2); + position: absolute; + z-index: 9; +} + +.ace_highlight-marker { + background-color: rgba(255, 255, 0,0.2); + position: absolute; + z-index: 8; +} + +.ace_mobile-menu { + position: absolute; + line-height: 1.5; + border-radius: 4px; + -ms-user-select: none; + -moz-user-select: none; + -webkit-user-select: none; + user-select: none; + background: white; + box-shadow: 1px 3px 2px grey; + border: 1px solid #dcdcdc; + color: black; +} +.ace_dark > .ace_mobile-menu { + background: #333; + color: #ccc; + box-shadow: 1px 3px 2px grey; + border: 1px solid #444; + +} +.ace_mobile-button { + padding: 2px; + cursor: pointer; + overflow: hidden; +} +.ace_mobile-button:hover { + background-color: #eee; + opacity:1; +} +.ace_mobile-button:active { + background-color: #ddd; +} + +.ace_placeholder { + font-family: arial; + transform: scale(0.9); + transform-origin: left; + white-space: pre; + opacity: 0.7; + margin: 0 10px; +} + +.ace_ghost_text { + opacity: 0.5; + font-style: italic; + white-space: pre; +} + +.ace_screenreader-only { + position:absolute; + left:-10000px; + top:auto; + width:1px; + height:1px; + overflow:hidden; +}`}),ace.define("ace/layer/decorators",["require","exports","module","ace/lib/dom","ace/lib/oop","ace/lib/event_emitter"],function(e,h,m){var g=e("../lib/dom"),a=e("../lib/oop"),u=e("../lib/event_emitter").EventEmitter,r=function(){function f(l,n){this.canvas=g.createElement("canvas"),this.renderer=n,this.pixelRatio=1,this.maxHeight=n.layerConfig.maxHeight,this.lineHeight=n.layerConfig.lineHeight,this.canvasHeight=l.parent.scrollHeight,this.heightRatio=this.canvasHeight/this.maxHeight,this.canvasWidth=l.width,this.minDecorationHeight=2*this.pixelRatio|0,this.halfMinDecorationHeight=this.minDecorationHeight/2|0,this.canvas.width=this.canvasWidth,this.canvas.height=this.canvasHeight,this.canvas.style.top=0+"px",this.canvas.style.right=0+"px",this.canvas.style.zIndex=7+"px",this.canvas.style.position="absolute",this.colors={},this.colors.dark={error:"rgba(255, 18, 18, 1)",warning:"rgba(18, 136, 18, 1)",info:"rgba(18, 18, 136, 1)"},this.colors.light={error:"rgb(255,51,51)",warning:"rgb(32,133,72)",info:"rgb(35,68,138)"},l.element.appendChild(this.canvas)}return f.prototype.$updateDecorators=function(l){var n=this.renderer.theme.isDark===!0?this.colors.dark:this.colors.light;if(l){this.maxHeight=l.maxHeight,this.lineHeight=l.lineHeight,this.canvasHeight=l.height;var i=(l.lastRow+1)*this.lineHeight;iT.priority?1:0}var c=this.renderer.session.$annotations;if(o.clearRect(0,0,this.canvas.width,this.canvas.height),c){var p={info:1,warning:2,error:3};c.forEach(function(k){k.priority=p[k.type]||null}),c=c.sort(s);for(var $=this.renderer.session.$foldData,v=0;vthis.canvasHeight&&(O=this.canvasHeight-this.halfMinDecorationHeight),b=Math.round(O-this.halfMinDecorationHeight),E=Math.round(O+this.halfMinDecorationHeight)}o.fillStyle=n[c[v].type]||null,o.fillRect(0,_,this.canvasWidth,E-b)}}var M=this.renderer.session.selection.getCursor();if(M){var y=this.compensateFoldRows(M.row,$),_=Math.round((M.row-y)*this.lineHeight*this.heightRatio);o.fillStyle="rgba(0, 0, 0, 0.5)",o.fillRect(0,_,this.canvasWidth,2)}},f.prototype.compensateFoldRows=function(l,n){var i=0;if(n&&n.length>0)for(var o=0;on[o].start.row&&l=n[o].end.row&&(i+=n[o].end.row-n[o].start.row);return i},f}();a.implement(r.prototype,u),h.Decorator=r}),ace.define("ace/virtual_renderer",["require","exports","module","ace/lib/oop","ace/lib/dom","ace/lib/lang","ace/config","ace/layer/gutter","ace/layer/marker","ace/layer/text","ace/layer/cursor","ace/scrollbar","ace/scrollbar","ace/scrollbar_custom","ace/scrollbar_custom","ace/renderloop","ace/layer/font_metrics","ace/lib/event_emitter","ace/css/editor-css","ace/layer/decorators","ace/lib/useragent"],function(e,h,m){var g=e("./lib/oop"),a=e("./lib/dom"),u=e("./lib/lang"),r=e("./config"),f=e("./layer/gutter").Gutter,l=e("./layer/marker").Marker,n=e("./layer/text").Text,i=e("./layer/cursor").Cursor,o=e("./scrollbar").HScrollBar,s=e("./scrollbar").VScrollBar,c=e("./scrollbar_custom").HScrollBar,p=e("./scrollbar_custom").VScrollBar,$=e("./renderloop").RenderLoop,v=e("./layer/font_metrics").FontMetrics,C=e("./lib/event_emitter").EventEmitter,y=e("./css/editor-css"),_=e("./layer/decorators").Decorator,b=e("./lib/useragent");a.importCssString(y,"ace_editor.css",!1);var E=function(){function x(O,M){var k=this;this.container=O||a.createElement("div"),a.addCssClass(this.container,"ace_editor"),a.HI_DPI&&a.addCssClass(this.container,"ace_hidpi"),this.setTheme(M),r.get("useStrictCSP")==null&&r.set("useStrictCSP",!1),this.$gutter=a.createElement("div"),this.$gutter.className="ace_gutter",this.container.appendChild(this.$gutter),this.$gutter.setAttribute("aria-hidden","true"),this.scroller=a.createElement("div"),this.scroller.className="ace_scroller",this.container.appendChild(this.scroller),this.content=a.createElement("div"),this.content.className="ace_content",this.scroller.appendChild(this.content),this.$gutterLayer=new f(this.$gutter),this.$gutterLayer.on("changeGutterWidth",this.onGutterResize.bind(this)),this.$markerBack=new l(this.content);var T=this.$textLayer=new n(this.content);this.canvas=T.element,this.$markerFront=new l(this.content),this.$cursorLayer=new i(this.content),this.$horizScroll=!1,this.$vScroll=!1,this.scrollBar=this.scrollBarV=new s(this.container,this),this.scrollBarH=new o(this.container,this),this.scrollBarV.on("scroll",function(S){k.$scrollAnimation||k.session.setScrollTop(S.data-k.scrollMargin.top)}),this.scrollBarH.on("scroll",function(S){k.$scrollAnimation||k.session.setScrollLeft(S.data-k.scrollMargin.left)}),this.scrollTop=0,this.scrollLeft=0,this.cursorPos={row:0,column:0},this.$fontMetrics=new v(this.container),this.$textLayer.$setFontMetrics(this.$fontMetrics),this.$textLayer.on("changeCharacterSize",function(S){k.updateCharacterSize(),k.onResize(!0,k.gutterWidth,k.$size.width,k.$size.height),k._signal("changeCharacterSize",S)}),this.$size={width:0,height:0,scrollerHeight:0,scrollerWidth:0,$dirty:!0},this.layerConfig={width:1,padding:0,firstRow:0,firstRowScreen:0,lastRow:0,lineHeight:0,characterWidth:0,minHeight:1,maxHeight:1,offset:0,height:1,gutterOffset:1},this.scrollMargin={left:0,right:0,top:0,bottom:0,v:0,h:0},this.margin={left:0,right:0,top:0,bottom:0,v:0,h:0},this.$keepTextAreaAtCursor=!b.isIOS,this.$loop=new $(this.$renderChanges.bind(this),this.container.ownerDocument.defaultView),this.$loop.schedule(this.CHANGE_FULL),this.updateCharacterSize(),this.setPadding(4),this.$addResizeObserver(),r.resetOptions(this),r._signal("renderer",this)}return x.prototype.updateCharacterSize=function(){this.$textLayer.allowBoldFonts!=this.$allowBoldFonts&&(this.$allowBoldFonts=this.$textLayer.allowBoldFonts,this.setStyle("ace_nobold",!this.$allowBoldFonts)),this.layerConfig.characterWidth=this.characterWidth=this.$textLayer.getCharacterWidth(),this.layerConfig.lineHeight=this.lineHeight=this.$textLayer.getLineHeight(),this.$updatePrintMargin(),a.setStyle(this.scroller.style,"line-height",this.lineHeight+"px")},x.prototype.setSession=function(O){this.session&&this.session.doc.off("changeNewLineMode",this.onChangeNewLineMode),this.session=O,O&&this.scrollMargin.top&&O.getScrollTop()<=0&&O.setScrollTop(-this.scrollMargin.top),this.$cursorLayer.setSession(O),this.$markerBack.setSession(O),this.$markerFront.setSession(O),this.$gutterLayer.setSession(O),this.$textLayer.setSession(O),!!O&&(this.$loop.schedule(this.CHANGE_FULL),this.session.$setFontMetrics(this.$fontMetrics),this.scrollBarH.scrollLeft=this.scrollBarV.scrollTop=null,this.onChangeNewLineMode=this.onChangeNewLineMode.bind(this),this.onChangeNewLineMode(),this.session.doc.on("changeNewLineMode",this.onChangeNewLineMode))},x.prototype.updateLines=function(O,M,k){if(M===void 0&&(M=1/0),this.$changedLines?(this.$changedLines.firstRow>O&&(this.$changedLines.firstRow=O),this.$changedLines.lastRowthis.layerConfig.lastRow||this.$loop.schedule(this.CHANGE_LINES)},x.prototype.onChangeNewLineMode=function(){this.$loop.schedule(this.CHANGE_TEXT),this.$textLayer.$updateEolChar(),this.session.$bidiHandler.setEolChar(this.$textLayer.EOL_CHAR)},x.prototype.onChangeTabSize=function(){this.$loop.schedule(this.CHANGE_TEXT|this.CHANGE_MARKER),this.$textLayer.onChangeTabSize()},x.prototype.updateText=function(){this.$loop.schedule(this.CHANGE_TEXT)},x.prototype.updateFull=function(O){O?this.$renderChanges(this.CHANGE_FULL,!0):this.$loop.schedule(this.CHANGE_FULL)},x.prototype.updateFontSize=function(){this.$textLayer.checkForSizeChanges()},x.prototype.$updateSizeAsync=function(){this.$loop.pending?this.$size.$dirty=!0:this.onResize()},x.prototype.onResize=function(O,M,k,T){if(!(this.resizing>2)){this.resizing>0?this.resizing++:this.resizing=O?1:0;var S=this.container;T||(T=S.clientHeight||S.scrollHeight),k||(k=S.clientWidth||S.scrollWidth);var w=this.$updateCachedSize(O,M,k,T);if(this.$resizeTimer&&this.$resizeTimer.cancel(),!this.$size.scrollerHeight||!k&&!T)return this.resizing=0;O&&(this.$gutterLayer.$padding=null),O?this.$renderChanges(w|this.$changes,!0):this.$loop.schedule(w|this.$changes),this.resizing&&(this.resizing=0),this.scrollBarH.scrollLeft=this.scrollBarV.scrollTop=null,this.$customScrollbar&&this.$updateCustomScrollbar(!0)}},x.prototype.$updateCachedSize=function(O,M,k,T){T-=this.$extraHeight||0;var S=0,w=this.$size,L={width:w.width,height:w.height,scrollerHeight:w.scrollerHeight,scrollerWidth:w.scrollerWidth};if(T&&(O||w.height!=T)&&(w.height=T,S|=this.CHANGE_SIZE,w.scrollerHeight=w.height,this.$horizScroll&&(w.scrollerHeight-=this.scrollBarH.getHeight()),this.scrollBarV.setHeight(w.scrollerHeight),this.scrollBarV.element.style.bottom=this.scrollBarH.getHeight()+"px",S=S|this.CHANGE_SCROLL),k&&(O||w.width!=k)){S|=this.CHANGE_SIZE,w.width=k,M==null&&(M=this.$showGutter?this.$gutter.offsetWidth:0),this.gutterWidth=M,a.setStyle(this.scrollBarH.element.style,"left",M+"px"),a.setStyle(this.scroller.style,"left",M+this.margin.left+"px"),w.scrollerWidth=Math.max(0,k-M-this.scrollBarV.getWidth()-this.margin.h),a.setStyle(this.$gutter.style,"left",this.margin.left+"px");var q=this.scrollBarV.getWidth()+"px";a.setStyle(this.scrollBarH.element.style,"right",q),a.setStyle(this.scroller.style,"right",q),a.setStyle(this.scroller.style,"bottom",this.scrollBarH.getHeight()),this.scrollBarH.setWidth(w.scrollerWidth),(this.session&&this.session.getUseWrapMode()&&this.adjustWrapLimit()||O)&&(S|=this.CHANGE_FULL)}return w.$dirty=!k||!T,S&&this._signal("resize",L),S},x.prototype.onGutterResize=function(O){var M=this.$showGutter?O:0;M!=this.gutterWidth&&(this.$changes|=this.$updateCachedSize(!0,M,this.$size.width,this.$size.height)),this.session.getUseWrapMode()&&this.adjustWrapLimit()?this.$loop.schedule(this.CHANGE_FULL):this.$size.$dirty?this.$loop.schedule(this.CHANGE_FULL):this.$computeLayerConfig()},x.prototype.adjustWrapLimit=function(){var O=this.$size.scrollerWidth-this.$padding*2,M=Math.floor(O/this.characterWidth);return this.session.adjustWrapLimit(M,this.$showPrintMargin&&this.$printMarginColumn)},x.prototype.setAnimatedScroll=function(O){this.setOption("animatedScroll",O)},x.prototype.getAnimatedScroll=function(){return this.$animatedScroll},x.prototype.setShowInvisibles=function(O){this.setOption("showInvisibles",O),this.session.$bidiHandler.setShowInvisibles(O)},x.prototype.getShowInvisibles=function(){return this.getOption("showInvisibles")},x.prototype.getDisplayIndentGuides=function(){return this.getOption("displayIndentGuides")},x.prototype.setDisplayIndentGuides=function(O){this.setOption("displayIndentGuides",O)},x.prototype.getHighlightIndentGuides=function(){return this.getOption("highlightIndentGuides")},x.prototype.setHighlightIndentGuides=function(O){this.setOption("highlightIndentGuides",O)},x.prototype.setShowPrintMargin=function(O){this.setOption("showPrintMargin",O)},x.prototype.getShowPrintMargin=function(){return this.getOption("showPrintMargin")},x.prototype.setPrintMarginColumn=function(O){this.setOption("printMarginColumn",O)},x.prototype.getPrintMarginColumn=function(){return this.getOption("printMarginColumn")},x.prototype.getShowGutter=function(){return this.getOption("showGutter")},x.prototype.setShowGutter=function(O){return this.setOption("showGutter",O)},x.prototype.getFadeFoldWidgets=function(){return this.getOption("fadeFoldWidgets")},x.prototype.setFadeFoldWidgets=function(O){this.setOption("fadeFoldWidgets",O)},x.prototype.setHighlightGutterLine=function(O){this.setOption("highlightGutterLine",O)},x.prototype.getHighlightGutterLine=function(){return this.getOption("highlightGutterLine")},x.prototype.$updatePrintMargin=function(){if(!(!this.$showPrintMargin&&!this.$printMarginEl)){if(!this.$printMarginEl){var O=a.createElement("div");O.className="ace_layer ace_print-margin-layer",this.$printMarginEl=a.createElement("div"),this.$printMarginEl.className="ace_print-margin",O.appendChild(this.$printMarginEl),this.content.insertBefore(O,this.content.firstChild)}var M=this.$printMarginEl.style;M.left=Math.round(this.characterWidth*this.$printMarginColumn+this.$padding)+"px",M.visibility=this.$showPrintMargin?"visible":"hidden",this.session&&this.session.$wrap==-1&&this.adjustWrapLimit()}},x.prototype.getContainerElement=function(){return this.container},x.prototype.getMouseEventTarget=function(){return this.scroller},x.prototype.getTextAreaContainer=function(){return this.container},x.prototype.$moveTextAreaToCursor=function(){if(!this.$isMousePressed){var O=this.textarea.style,M=this.$composition;if(!this.$keepTextAreaAtCursor&&!M){a.translate(this.textarea,-100,0);return}var k=this.$cursorLayer.$pixelPos;if(!!k){M&&M.markerRange&&(k=this.$cursorLayer.getPixelPosition(M.markerRange.start,!0));var T=this.layerConfig,S=k.top,w=k.left;S-=T.offset;var L=M&&M.useTextareaForIME||b.isMobile?this.lineHeight:1;if(S<0||S>T.height-L){a.translate(this.textarea,0,0);return}var q=1,A=this.$size.height-L;if(!M)S+=this.lineHeight;else if(M.useTextareaForIME){var I=this.textarea.value;q=this.characterWidth*this.session.$getStringScreenWidth(I)[0]}else S+=this.lineHeight+2;w-=this.scrollLeft,w>this.$size.scrollerWidth-q&&(w=this.$size.scrollerWidth-q),w+=this.gutterWidth+this.margin.left,a.setStyle(O,"height",L+"px"),a.setStyle(O,"width",q+"px"),a.translate(this.textarea,Math.min(w,this.$size.scrollerWidth-q),Math.min(S,A))}}},x.prototype.getFirstVisibleRow=function(){return this.layerConfig.firstRow},x.prototype.getFirstFullyVisibleRow=function(){return this.layerConfig.firstRow+(this.layerConfig.offset===0?0:1)},x.prototype.getLastFullyVisibleRow=function(){var O=this.layerConfig,M=O.lastRow,k=this.session.documentToScreenRow(M,0)*O.lineHeight;return k-this.session.getScrollTop()>O.height-O.lineHeight?M-1:M},x.prototype.getLastVisibleRow=function(){return this.layerConfig.lastRow},x.prototype.setPadding=function(O){this.$padding=O,this.$textLayer.setPadding(O),this.$cursorLayer.setPadding(O),this.$markerFront.setPadding(O),this.$markerBack.setPadding(O),this.$loop.schedule(this.CHANGE_FULL),this.$updatePrintMargin()},x.prototype.setScrollMargin=function(O,M,k,T){var S=this.scrollMargin;S.top=O|0,S.bottom=M|0,S.right=T|0,S.left=k|0,S.v=S.top+S.bottom,S.h=S.left+S.right,S.top&&this.scrollTop<=0&&this.session&&this.session.setScrollTop(-S.top),this.updateFull()},x.prototype.setMargin=function(O,M,k,T){var S=this.margin;S.top=O|0,S.bottom=M|0,S.right=T|0,S.left=k|0,S.v=S.top+S.bottom,S.h=S.left+S.right,this.$updateCachedSize(!0,this.gutterWidth,this.$size.width,this.$size.height),this.updateFull()},x.prototype.getHScrollBarAlwaysVisible=function(){return this.$hScrollBarAlwaysVisible},x.prototype.setHScrollBarAlwaysVisible=function(O){this.setOption("hScrollBarAlwaysVisible",O)},x.prototype.getVScrollBarAlwaysVisible=function(){return this.$vScrollBarAlwaysVisible},x.prototype.setVScrollBarAlwaysVisible=function(O){this.setOption("vScrollBarAlwaysVisible",O)},x.prototype.$updateScrollBarV=function(){var O=this.layerConfig.maxHeight,M=this.$size.scrollerHeight;!this.$maxLines&&this.$scrollPastEnd&&(O-=(M-this.lineHeight)*this.$scrollPastEnd,this.scrollTop>O-M&&(O=this.scrollTop+M,this.scrollBarV.scrollTop=null)),this.scrollBarV.setScrollHeight(O+this.scrollMargin.v),this.scrollBarV.setScrollTop(this.scrollTop+this.scrollMargin.top)},x.prototype.$updateScrollBarH=function(){this.scrollBarH.setScrollWidth(this.layerConfig.width+2*this.$padding+this.scrollMargin.h),this.scrollBarH.setScrollLeft(this.scrollLeft+this.scrollMargin.left)},x.prototype.freeze=function(){this.$frozen=!0},x.prototype.unfreeze=function(){this.$frozen=!1},x.prototype.$renderChanges=function(O,M){if(this.$changes&&(O|=this.$changes,this.$changes=0),!this.session||!this.container.offsetWidth||this.$frozen||!O&&!M){this.$changes|=O;return}if(this.$size.$dirty)return this.$changes|=O,this.onResize(!0);this.lineHeight||this.$textLayer.checkForSizeChanges(),this._signal("beforeRender",O),this.session&&this.session.$bidiHandler&&this.session.$bidiHandler.updateCharacterWidths(this.$fontMetrics);var k=this.layerConfig;if(O&this.CHANGE_FULL||O&this.CHANGE_SIZE||O&this.CHANGE_TEXT||O&this.CHANGE_LINES||O&this.CHANGE_SCROLL||O&this.CHANGE_H_SCROLL){if(O|=this.$computeLayerConfig()|this.$loop.clear(),k.firstRow!=this.layerConfig.firstRow&&k.firstRowScreen==this.layerConfig.firstRowScreen){var T=this.scrollTop+(k.firstRow-Math.max(this.layerConfig.firstRow,0))*this.lineHeight;T>0&&(this.scrollTop=T,O=O|this.CHANGE_SCROLL,O|=this.$computeLayerConfig()|this.$loop.clear())}k=this.layerConfig,this.$updateScrollBarV(),O&this.CHANGE_H_SCROLL&&this.$updateScrollBarH(),a.translate(this.content,-this.scrollLeft,-k.offset);var S=k.width+2*this.$padding+"px",w=k.minHeight+"px";a.setStyle(this.content.style,"width",S),a.setStyle(this.content.style,"height",w)}if(O&this.CHANGE_H_SCROLL&&(a.translate(this.content,-this.scrollLeft,-k.offset),this.scroller.className=this.scrollLeft<=0?"ace_scroller ":"ace_scroller ace_scroll-left ",this.enableKeyboardAccessibility&&(this.scroller.className+=this.keyboardFocusClassName)),O&this.CHANGE_FULL){this.$changedLines=null,this.$textLayer.update(k),this.$showGutter&&this.$gutterLayer.update(k),this.$customScrollbar&&this.$scrollDecorator.$updateDecorators(k),this.$markerBack.update(k),this.$markerFront.update(k),this.$cursorLayer.update(k),this.$moveTextAreaToCursor(),this._signal("afterRender",O);return}if(O&this.CHANGE_SCROLL){this.$changedLines=null,O&this.CHANGE_TEXT||O&this.CHANGE_LINES?this.$textLayer.update(k):this.$textLayer.scrollLines(k),this.$showGutter&&(O&this.CHANGE_GUTTER||O&this.CHANGE_LINES?this.$gutterLayer.update(k):this.$gutterLayer.scrollLines(k)),this.$customScrollbar&&this.$scrollDecorator.$updateDecorators(k),this.$markerBack.update(k),this.$markerFront.update(k),this.$cursorLayer.update(k),this.$moveTextAreaToCursor(),this._signal("afterRender",O);return}O&this.CHANGE_TEXT?(this.$changedLines=null,this.$textLayer.update(k),this.$showGutter&&this.$gutterLayer.update(k),this.$customScrollbar&&this.$scrollDecorator.$updateDecorators(k)):O&this.CHANGE_LINES?((this.$updateLines()||O&this.CHANGE_GUTTER&&this.$showGutter)&&this.$gutterLayer.update(k),this.$customScrollbar&&this.$scrollDecorator.$updateDecorators(k)):O&this.CHANGE_TEXT||O&this.CHANGE_GUTTER?(this.$showGutter&&this.$gutterLayer.update(k),this.$customScrollbar&&this.$scrollDecorator.$updateDecorators(k)):O&this.CHANGE_CURSOR&&(this.$highlightGutterLine&&this.$gutterLayer.updateLineHighlight(k),this.$customScrollbar&&this.$scrollDecorator.$updateDecorators(k)),O&this.CHANGE_CURSOR&&(this.$cursorLayer.update(k),this.$moveTextAreaToCursor()),O&(this.CHANGE_MARKER|this.CHANGE_MARKER_FRONT)&&this.$markerFront.update(k),O&(this.CHANGE_MARKER|this.CHANGE_MARKER_BACK)&&this.$markerBack.update(k),this._signal("afterRender",O)},x.prototype.$autosize=function(){var O=this.session.getScreenLength()*this.lineHeight,M=this.$maxLines*this.lineHeight,k=Math.min(M,Math.max((this.$minLines||1)*this.lineHeight,O))+this.scrollMargin.v+(this.$extraHeight||0);this.$horizScroll&&(k+=this.scrollBarH.getHeight()),this.$maxPixelHeight&&k>this.$maxPixelHeight&&(k=this.$maxPixelHeight);var T=k<=2*this.lineHeight,S=!T&&O>M;if(k!=this.desiredHeight||this.$size.height!=this.desiredHeight||S!=this.$vScroll){S!=this.$vScroll&&(this.$vScroll=S,this.scrollBarV.setVisible(S));var w=this.container.clientWidth;this.container.style.height=k+"px",this.$updateCachedSize(!0,this.$gutterWidth,w,k),this.desiredHeight=k,this._signal("autosize")}},x.prototype.$computeLayerConfig=function(){var O=this.session,M=this.$size,k=M.height<=2*this.lineHeight,T=this.session.getScreenLength(),S=T*this.lineHeight,w=this.$getLongestLine(),L=!k&&(this.$hScrollBarAlwaysVisible||M.scrollerWidth-w-2*this.$padding<0),q=this.$horizScroll!==L;q&&(this.$horizScroll=L,this.scrollBarH.setVisible(L));var A=this.$vScroll;this.$maxLines&&this.lineHeight>1&&this.$autosize();var I=M.scrollerHeight+this.lineHeight,F=!this.$maxLines&&this.$scrollPastEnd?(M.scrollerHeight-this.lineHeight)*this.$scrollPastEnd:0;S+=F;var V=this.scrollMargin;this.session.setScrollTop(Math.max(-V.top,Math.min(this.scrollTop,S-M.scrollerHeight+V.bottom))),this.session.setScrollLeft(Math.max(-V.left,Math.min(this.scrollLeft,w+2*this.$padding-M.scrollerWidth+V.right)));var R=!k&&(this.$vScrollBarAlwaysVisible||M.scrollerHeight-S+F<0||this.scrollTop>V.top),B=A!==R;B&&(this.$vScroll=R,this.scrollBarV.setVisible(R));var N=this.scrollTop%this.lineHeight,P=Math.ceil(I/this.lineHeight)-1,j=Math.max(0,Math.round((this.scrollTop-N)/this.lineHeight)),D=j+P,W,H,z=this.lineHeight;j=O.screenToDocumentRow(j,0);var K=O.getFoldLine(j);K&&(j=K.start.row),W=O.documentToScreenRow(j,0),H=O.getRowLength(j)*z,D=Math.min(O.screenToDocumentRow(D,0),O.getLength()-1),I=M.scrollerHeight+O.getRowLength(D)*z+H,N=this.scrollTop-W*z;var Z=0;return(this.layerConfig.width!=w||q)&&(Z=this.CHANGE_H_SCROLL),(q||B)&&(Z|=this.$updateCachedSize(!0,this.gutterWidth,M.width,M.height),this._signal("scrollbarVisibilityChanged"),B&&(w=this.$getLongestLine())),this.layerConfig={width:w,padding:this.$padding,firstRow:j,firstRowScreen:W,lastRow:D,lineHeight:z,characterWidth:this.characterWidth,minHeight:I,maxHeight:S,offset:N,gutterOffset:z?Math.max(0,Math.ceil((N+M.height-M.scrollerHeight)/z)):0,height:this.$size.scrollerHeight},this.session.$bidiHandler&&this.session.$bidiHandler.setContentWidth(w-this.$padding),Z},x.prototype.$updateLines=function(){if(!!this.$changedLines){var O=this.$changedLines.firstRow,M=this.$changedLines.lastRow;this.$changedLines=null;var k=this.layerConfig;if(!(O>k.lastRow+1)&&!(Mthis.$textLayer.MAX_LINE_LENGTH&&(O=this.$textLayer.MAX_LINE_LENGTH+30),Math.max(this.$size.scrollerWidth-2*this.$padding,Math.round(O*this.characterWidth))},x.prototype.updateFrontMarkers=function(){this.$markerFront.setMarkers(this.session.getMarkers(!0)),this.$loop.schedule(this.CHANGE_MARKER_FRONT)},x.prototype.updateBackMarkers=function(){this.$markerBack.setMarkers(this.session.getMarkers()),this.$loop.schedule(this.CHANGE_MARKER_BACK)},x.prototype.addGutterDecoration=function(O,M){this.$gutterLayer.addGutterDecoration(O,M)},x.prototype.removeGutterDecoration=function(O,M){this.$gutterLayer.removeGutterDecoration(O,M)},x.prototype.updateBreakpoints=function(O){this._rows=O,this.$loop.schedule(this.CHANGE_GUTTER)},x.prototype.setAnnotations=function(O){this.$gutterLayer.setAnnotations(O),this.$loop.schedule(this.CHANGE_GUTTER)},x.prototype.updateCursor=function(){this.$loop.schedule(this.CHANGE_CURSOR)},x.prototype.hideCursor=function(){this.$cursorLayer.hideCursor()},x.prototype.showCursor=function(){this.$cursorLayer.showCursor()},x.prototype.scrollSelectionIntoView=function(O,M,k){this.scrollCursorIntoView(O,k),this.scrollCursorIntoView(M,k)},x.prototype.scrollCursorIntoView=function(O,M,k){if(this.$size.scrollerHeight!==0){var T=this.$cursorLayer.getPixelPosition(O),S=T.left,w=T.top,L=k&&k.top||0,q=k&&k.bottom||0;this.$scrollAnimation&&(this.$stopAnimation=!0);var A=this.$scrollAnimation?this.session.getScrollTop():this.scrollTop;A+L>w?(M&&A+L>w+this.lineHeight&&(w-=M*this.$size.scrollerHeight),w===0&&(w=-this.scrollMargin.top),this.session.setScrollTop(w)):A+this.$size.scrollerHeight-q=1-this.scrollMargin.top||M>0&&this.session.getScrollTop()+this.$size.scrollerHeight-this.layerConfig.maxHeight<-1+this.scrollMargin.bottom||O<0&&this.session.getScrollLeft()>=1-this.scrollMargin.left||O>0&&this.session.getScrollLeft()+this.$size.scrollerWidth-this.layerConfig.width<-1+this.scrollMargin.right)return!0},x.prototype.pixelToScreenCoordinates=function(O,M){var k;if(this.$hasCssTransforms){k={top:0,left:0};var T=this.$fontMetrics.transformCoordinates([O,M]);O=T[1]-this.gutterWidth-this.margin.left,M=T[0]}else k=this.scroller.getBoundingClientRect();var S=O+this.scrollLeft-k.left-this.$padding,w=S/this.characterWidth,L=Math.floor((M+this.scrollTop-k.top)/this.lineHeight),q=this.$blockCursor?Math.floor(w):Math.round(w);return{row:L,column:q,side:w-q>0?1:-1,offsetX:S}},x.prototype.screenToTextCoordinates=function(O,M){var k;if(this.$hasCssTransforms){k={top:0,left:0};var T=this.$fontMetrics.transformCoordinates([O,M]);O=T[1]-this.gutterWidth-this.margin.left,M=T[0]}else k=this.scroller.getBoundingClientRect();var S=O+this.scrollLeft-k.left-this.$padding,w=S/this.characterWidth,L=this.$blockCursor?Math.floor(w):Math.round(w),q=Math.floor((M+this.scrollTop-k.top)/this.lineHeight);return this.session.screenToDocumentPosition(q,Math.max(L,0),S)},x.prototype.textToScreenCoordinates=function(O,M){var k=this.scroller.getBoundingClientRect(),T=this.session.documentToScreenPosition(O,M),S=this.$padding+(this.session.$bidiHandler.isBidiRow(T.row,O)?this.session.$bidiHandler.getPosLeft(T.column):Math.round(T.column*this.characterWidth)),w=T.row*this.lineHeight;return{pageX:k.left+S-this.scrollLeft,pageY:k.top+w-this.scrollTop}},x.prototype.visualizeFocus=function(){a.addCssClass(this.container,"ace_focus")},x.prototype.visualizeBlur=function(){a.removeCssClass(this.container,"ace_focus")},x.prototype.showComposition=function(O){this.$composition=O,O.cssText||(O.cssText=this.textarea.style.cssText),O.useTextareaForIME==null&&(O.useTextareaForIME=this.$useTextareaForIME),this.$useTextareaForIME?(a.addCssClass(this.textarea,"ace_composition"),this.textarea.style.cssText="",this.$moveTextAreaToCursor(),this.$cursorLayer.element.style.display="none"):O.markerId=this.session.addMarker(O.markerRange,"ace_composition_marker","text")},x.prototype.setCompositionText=function(O){var M=this.session.selection.cursor;this.addToken(O,"composition_placeholder",M.row,M.column),this.$moveTextAreaToCursor()},x.prototype.hideComposition=function(){if(!!this.$composition){this.$composition.markerId&&this.session.removeMarker(this.$composition.markerId),a.removeCssClass(this.textarea,"ace_composition"),this.textarea.style.cssText=this.$composition.cssText;var O=this.session.selection.cursor;this.removeExtraToken(O.row,O.column),this.$composition=null,this.$cursorLayer.element.style.display=""}},x.prototype.setGhostText=function(O,M){var k=this.session.selection.cursor,T=M||{row:k.row,column:k.column};this.removeGhostText();var S=O.split(` +`);if(this.addToken(S[0],"ghost_text",T.row,T.column),this.$ghostText={text:O,position:{row:T.row,column:T.column}},S.length>1){this.$ghostTextWidget={text:S.slice(1).join(` +`),row:T.row,column:T.column,className:"ace_ghost_text"},this.session.widgetManager.addLineWidget(this.$ghostTextWidget);var w=this.$cursorLayer.getPixelPosition(T,!0),L=this.container,q=L.getBoundingClientRect().height,A=S.length*this.lineHeight,I=A1||Math.abs(O.$size.height-T)>1?O.$resizeTimer.delay():O.$resizeTimer.cancel()}),this.$resizeObserver.observe(this.container)}},x}();E.prototype.CHANGE_CURSOR=1,E.prototype.CHANGE_MARKER=2,E.prototype.CHANGE_GUTTER=4,E.prototype.CHANGE_SCROLL=8,E.prototype.CHANGE_LINES=16,E.prototype.CHANGE_TEXT=32,E.prototype.CHANGE_SIZE=64,E.prototype.CHANGE_MARKER_BACK=128,E.prototype.CHANGE_MARKER_FRONT=256,E.prototype.CHANGE_FULL=512,E.prototype.CHANGE_H_SCROLL=1024,E.prototype.$changes=0,E.prototype.$padding=null,E.prototype.$frozen=!1,E.prototype.STEPS=8,g.implement(E.prototype,C),r.defineOptions(E.prototype,"renderer",{useResizeObserver:{set:function(x){!x&&this.$resizeObserver?(this.$resizeObserver.disconnect(),this.$resizeTimer.cancel(),this.$resizeTimer=this.$resizeObserver=null):x&&!this.$resizeObserver&&this.$addResizeObserver()}},animatedScroll:{initialValue:!1},showInvisibles:{set:function(x){this.$textLayer.setShowInvisibles(x)&&this.$loop.schedule(this.CHANGE_TEXT)},initialValue:!1},showPrintMargin:{set:function(){this.$updatePrintMargin()},initialValue:!0},printMarginColumn:{set:function(){this.$updatePrintMargin()},initialValue:80},printMargin:{set:function(x){typeof x=="number"&&(this.$printMarginColumn=x),this.$showPrintMargin=!!x,this.$updatePrintMargin()},get:function(){return this.$showPrintMargin&&this.$printMarginColumn}},showGutter:{set:function(x){this.$gutter.style.display=x?"block":"none",this.$loop.schedule(this.CHANGE_FULL),this.onGutterResize()},initialValue:!0},useSvgGutterIcons:{set:function(x){this.$gutterLayer.$useSvgGutterIcons=x},initialValue:!1},showFoldedAnnotations:{set:function(x){this.$gutterLayer.$showFoldedAnnotations=x},initialValue:!1},fadeFoldWidgets:{set:function(x){a.setCssClass(this.$gutter,"ace_fade-fold-widgets",x)},initialValue:!1},showFoldWidgets:{set:function(x){this.$gutterLayer.setShowFoldWidgets(x),this.$loop.schedule(this.CHANGE_GUTTER)},initialValue:!0},displayIndentGuides:{set:function(x){this.$textLayer.setDisplayIndentGuides(x)&&this.$loop.schedule(this.CHANGE_TEXT)},initialValue:!0},highlightIndentGuides:{set:function(x){this.$textLayer.setHighlightIndentGuides(x)==!0?this.$textLayer.$highlightIndentGuide():this.$textLayer.$clearActiveIndentGuide(this.$textLayer.$lines.cells)},initialValue:!0},highlightGutterLine:{set:function(x){this.$gutterLayer.setHighlightGutterLine(x),this.$loop.schedule(this.CHANGE_GUTTER)},initialValue:!0},hScrollBarAlwaysVisible:{set:function(x){(!this.$hScrollBarAlwaysVisible||!this.$horizScroll)&&this.$loop.schedule(this.CHANGE_SCROLL)},initialValue:!1},vScrollBarAlwaysVisible:{set:function(x){(!this.$vScrollBarAlwaysVisible||!this.$vScroll)&&this.$loop.schedule(this.CHANGE_SCROLL)},initialValue:!1},fontSize:{set:function(x){typeof x=="number"&&(x=x+"px"),this.container.style.fontSize=x,this.updateFontSize()},initialValue:12},fontFamily:{set:function(x){this.container.style.fontFamily=x,this.updateFontSize()}},maxLines:{set:function(x){this.updateFull()}},minLines:{set:function(x){this.$minLines<562949953421311||(this.$minLines=0),this.updateFull()}},maxPixelHeight:{set:function(x){this.updateFull()},initialValue:0},scrollPastEnd:{set:function(x){x=+x||0,this.$scrollPastEnd!=x&&(this.$scrollPastEnd=x,this.$loop.schedule(this.CHANGE_SCROLL))},initialValue:0,handlesSet:!0},fixedWidthGutter:{set:function(x){this.$gutterLayer.$fixedWidth=!!x,this.$loop.schedule(this.CHANGE_GUTTER)}},customScrollbar:{set:function(x){this.$updateCustomScrollbar(x)},initialValue:!1},theme:{set:function(x){this.setTheme(x)},get:function(){return this.$themeId||this.theme},initialValue:"./theme/textmate",handlesSet:!0},hasCssTransforms:{},useTextareaForIME:{initialValue:!b.isMobile&&!b.isIE}}),h.VirtualRenderer=E}),ace.define("ace/worker/worker_client",["require","exports","module","ace/lib/oop","ace/lib/net","ace/lib/event_emitter","ace/config"],function(e,h,m){var g=e("../lib/oop"),a=e("../lib/net"),u=e("../lib/event_emitter").EventEmitter,r=e("../config");function f(o){var s="importScripts('"+a.qualifyURL(o)+"');";try{return new Blob([s],{type:"application/javascript"})}catch{var c=window.BlobBuilder||window.WebKitBlobBuilder||window.MozBlobBuilder,p=new c;return p.append(s),p.getBlob("application/javascript")}}function l(o){if(typeof Worker=="undefined")return{postMessage:function(){},terminate:function(){}};if(r.get("loadWorkerFromBlob")){var s=f(o),c=window.URL||window.webkitURL,p=c.createObjectURL(s);return new Worker(p)}return new Worker(o)}var n=function(o){o.postMessage||(o=this.$createWorkerFromOldConfig.apply(this,arguments)),this.$worker=o,this.$sendDeltaQueue=this.$sendDeltaQueue.bind(this),this.changeListener=this.changeListener.bind(this),this.onMessage=this.onMessage.bind(this),this.callbackId=1,this.callbacks={},this.$worker.onmessage=this.onMessage};(function(){g.implement(this,u),this.$createWorkerFromOldConfig=function(o,s,c,p,$){if(e.nameToUrl&&!e.toUrl&&(e.toUrl=e.nameToUrl),r.get("packaged")||!e.toUrl)p=p||r.moduleUrl(s,"worker");else{var v=this.$normalizePath;p=p||v(e.toUrl("ace/worker/worker.js",null,"_"));var C={};o.forEach(function(y){C[y]=v(e.toUrl(y,null,"_").replace(/(\.js)?(\?.*)?$/,""))})}return this.$worker=l(p),$&&this.send("importScripts",$),this.$worker.postMessage({init:!0,tlns:C,module:s,classname:c}),this.$worker},this.onMessage=function(o){var s=o.data;switch(s.type){case"event":this._signal(s.name,{data:s.data});break;case"call":var c=this.callbacks[s.id];c&&(c(s.data),delete this.callbacks[s.id]);break;case"error":this.reportError(s.data);break;case"log":window.console&&console.log&&console.log.apply(console,s.data);break}},this.reportError=function(o){window.console&&console.error&&console.error(o)},this.$normalizePath=function(o){return a.qualifyURL(o)},this.terminate=function(){this._signal("terminate",{}),this.deltaQueue=null,this.$worker.terminate(),this.$worker.onerror=function(o){o.preventDefault()},this.$worker=null,this.$doc&&this.$doc.off("change",this.changeListener),this.$doc=null},this.send=function(o,s){this.$worker.postMessage({command:o,args:s})},this.call=function(o,s,c){if(c){var p=this.callbackId++;this.callbacks[p]=c,s.push(p)}this.send(o,s)},this.emit=function(o,s){try{s.data&&s.data.err&&(s.data.err={message:s.data.err.message,stack:s.data.err.stack,code:s.data.err.code}),this.$worker&&this.$worker.postMessage({event:o,data:{data:s.data}})}catch(c){console.error(c.stack)}},this.attachToDocument=function(o){this.$doc&&this.terminate(),this.$doc=o,this.call("setValue",[o.getValue()]),o.on("change",this.changeListener,!0)},this.changeListener=function(o){this.deltaQueue||(this.deltaQueue=[],setTimeout(this.$sendDeltaQueue,0)),o.action=="insert"?this.deltaQueue.push(o.start,o.lines):this.deltaQueue.push(o.start,o.end)},this.$sendDeltaQueue=function(){var o=this.deltaQueue;!o||(this.deltaQueue=null,o.length>50&&o.length>this.$doc.getLength()>>1?this.call("setValue",[this.$doc.getValue()]):this.emit("change",{data:o}))}}).call(n.prototype);var i=function(o,s,c){var p=null,$=!1,v=Object.create(u),C=[],y=new n({messageBuffer:C,terminate:function(){},postMessage:function(b){C.push(b),!!p&&($?setTimeout(_):_())}});y.setEmitSync=function(b){$=b};var _=function(){var b=C.shift();b.command?p[b.command].apply(p,b.args):b.event&&v._signal(b.event,b.data)};return v.postMessage=function(b){y.onMessage({data:b})},v.callback=function(b,E){this.postMessage({type:"call",id:E,data:b})},v.emit=function(b,E){this.postMessage({type:"event",name:b,data:E})},r.loadModule(["worker",s],function(b){for(p=new b[c](v);C.length;)_()}),y};h.UIWorkerClient=i,h.WorkerClient=n,h.createWorker=l}),ace.define("ace/placeholder",["require","exports","module","ace/range","ace/lib/event_emitter","ace/lib/oop"],function(e,h,m){var g=e("./range").Range,a=e("./lib/event_emitter").EventEmitter,u=e("./lib/oop"),r=function(){function f(l,n,i,o,s,c){var p=this;this.length=n,this.session=l,this.doc=l.getDocument(),this.mainClass=s,this.othersClass=c,this.$onUpdate=this.onUpdate.bind(this),this.doc.on("change",this.$onUpdate,!0),this.$others=o,this.$onCursorChange=function(){setTimeout(function(){p.onCursorChange()})},this.$pos=i;var $=l.getUndoManager().$undoStack||l.getUndoManager().$undostack||{length:-1};this.$undoStackDepth=$.length,this.setup(),l.selection.on("changeCursor",this.$onCursorChange)}return f.prototype.setup=function(){var l=this,n=this.doc,i=this.session;this.selectionBefore=i.selection.toJSON(),i.selection.inMultiSelectMode&&i.selection.toSingleRange(),this.pos=n.createAnchor(this.$pos.row,this.$pos.column);var o=this.pos;o.$insertRight=!0,o.detach(),o.markerId=i.addMarker(new g(o.row,o.column,o.row,o.column+this.length),this.mainClass,null,!1),this.others=[],this.$others.forEach(function(s){var c=n.createAnchor(s.row,s.column);c.$insertRight=!0,c.detach(),l.others.push(c)}),i.setUndoSelect(!1)},f.prototype.showOtherMarkers=function(){if(!this.othersActive){var l=this.session,n=this;this.othersActive=!0,this.others.forEach(function(i){i.markerId=l.addMarker(new g(i.row,i.column,i.row,i.column+n.length),n.othersClass,null,!1)})}},f.prototype.hideOtherMarkers=function(){if(!!this.othersActive){this.othersActive=!1;for(var l=0;l=this.pos.column&&n.start.column<=this.pos.column+this.length+1,s=n.start.column-this.pos.column;if(this.updateAnchors(l),o&&(this.length+=i),o&&!this.session.$fromUndo){if(l.action==="insert")for(var c=this.others.length-1;c>=0;c--){var p=this.others[c],$={row:p.row,column:p.column+s};this.doc.insertMergedLines($,l.lines)}else if(l.action==="remove")for(var c=this.others.length-1;c>=0;c--){var p=this.others[c],$={row:p.row,column:p.column+s};this.doc.remove(new g($.row,$.column,$.row,$.column-i))}}this.$updating=!1,this.updateMarkers()}},f.prototype.updateAnchors=function(l){this.pos.onChange(l);for(var n=this.others.length;n--;)this.others[n].onChange(l);this.updateMarkers()},f.prototype.updateMarkers=function(){if(!this.$updating){var l=this,n=this.session,i=function(s,c){n.removeMarker(s.markerId),s.markerId=n.addMarker(new g(s.row,s.column,s.row,s.column+l.length),c,null,!1)};i(this.pos,this.mainClass);for(var o=this.others.length;o--;)i(this.others[o],this.othersClass)}},f.prototype.onCursorChange=function(l){if(!(this.$updating||!this.session)){var n=this.session.selection.getCursor();n.row===this.pos.row&&n.column>=this.pos.column&&n.column<=this.pos.column+this.length?(this.showOtherMarkers(),this._emit("cursorEnter",l)):(this.hideOtherMarkers(),this._emit("cursorLeave",l))}},f.prototype.detach=function(){this.session.removeMarker(this.pos&&this.pos.markerId),this.hideOtherMarkers(),this.doc.off("change",this.$onUpdate),this.session.selection.off("changeCursor",this.$onCursorChange),this.session.setUndoSelect(!0),this.session=null},f.prototype.cancel=function(){if(this.$undoStackDepth!==-1){for(var l=this.session.getUndoManager(),n=(l.$undoStack||l.$undostack).length-this.$undoStackDepth,i=0;i1?a.multiSelect.joinSelections():a.multiSelect.splitIntoLines()},bindKey:{win:"Ctrl-Alt-L",mac:"Ctrl-Alt-L"},readOnly:!0},{name:"splitSelectionIntoLines",description:"Split into lines",exec:function(a){a.multiSelect.splitIntoLines()},readOnly:!0},{name:"alignCursors",description:"Align cursors",exec:function(a){a.alignCursors()},bindKey:{win:"Ctrl-Alt-A",mac:"Ctrl-Alt-A"},scrollIntoView:"cursor"},{name:"findAll",description:"Find all",exec:function(a){a.findAll()},bindKey:{win:"Ctrl-Alt-K",mac:"Ctrl-Alt-G"},scrollIntoView:"cursor",readOnly:!0}],h.multiSelectCommands=[{name:"singleSelection",description:"Single selection",bindKey:"esc",exec:function(a){a.exitMultiSelectMode()},scrollIntoView:"cursor",readOnly:!0,isAvailable:function(a){return a&&a.inMultiSelectMode}}];var g=e("../keyboard/hash_handler").HashHandler;h.keyboardHandler=new g(h.multiSelectCommands)}),ace.define("ace/multi_select",["require","exports","module","ace/range_list","ace/range","ace/selection","ace/mouse/multi_select_handler","ace/lib/event","ace/lib/lang","ace/commands/multi_select_commands","ace/search","ace/edit_session","ace/editor","ace/config"],function(e,h,m){var g=e("./range_list").RangeList,a=e("./range").Range,u=e("./selection").Selection,r=e("./mouse/multi_select_handler").onMouseDown,f=e("./lib/event"),l=e("./lib/lang"),n=e("./commands/multi_select_commands");h.commands=n.defaultCommands.concat(n.multiSelectCommands);var i=e("./search").Search,o=new i;function s(y,_,b){return o.$options.wrap=!0,o.$options.needle=_,o.$options.backwards=b==-1,o.find(y)}var c=e("./edit_session").EditSession;(function(){this.getSelectionMarkers=function(){return this.$selectionMarkers}}).call(c.prototype),function(){this.ranges=null,this.rangeList=null,this.addRange=function(y,_){if(!!y){if(!this.inMultiSelectMode&&this.rangeCount===0){var b=this.toOrientedRange();if(this.rangeList.add(b),this.rangeList.add(y),this.rangeList.ranges.length!=2)return this.rangeList.removeAll(),_||this.fromOrientedRange(y);this.rangeList.removeAll(),this.rangeList.add(b),this.$onAddRange(b)}y.cursor||(y.cursor=y.end);var E=this.rangeList.add(y);return this.$onAddRange(y),E.length&&this.$onRemoveRange(E),this.rangeCount>1&&!this.inMultiSelectMode&&(this._signal("multiSelect"),this.inMultiSelectMode=!0,this.session.$undoSelect=!1,this.rangeList.attach(this.session)),_||this.fromOrientedRange(y)}},this.toSingleRange=function(y){y=y||this.ranges[0];var _=this.rangeList.removeAll();_.length&&this.$onRemoveRange(_),y&&this.fromOrientedRange(y)},this.substractPoint=function(y){var _=this.rangeList.substractPoint(y);if(_)return this.$onRemoveRange(_),_[0]},this.mergeOverlappingRanges=function(){var y=this.rangeList.merge();y.length&&this.$onRemoveRange(y)},this.$onAddRange=function(y){this.rangeCount=this.rangeList.ranges.length,this.ranges.unshift(y),this._signal("addRange",{range:y})},this.$onRemoveRange=function(y){if(this.rangeCount=this.rangeList.ranges.length,this.rangeCount==1&&this.inMultiSelectMode){var _=this.rangeList.ranges.pop();y.push(_),this.rangeCount=0}for(var b=y.length;b--;){var E=this.ranges.indexOf(y[b]);this.ranges.splice(E,1)}this._signal("removeRange",{ranges:y}),this.rangeCount===0&&this.inMultiSelectMode&&(this.inMultiSelectMode=!1,this._signal("singleSelect"),this.session.$undoSelect=!0,this.rangeList.detach(this.session)),_=_||this.ranges[0],_&&!_.isEqual(this.getRange())&&this.fromOrientedRange(_)},this.$initRangeList=function(){this.rangeList||(this.rangeList=new g,this.ranges=[],this.rangeCount=0)},this.getAllRanges=function(){return this.rangeCount?this.rangeList.ranges.concat():[this.getRange()]},this.splitIntoLines=function(){for(var y=this.ranges.length?this.ranges:[this.getRange()],_=[],b=0;b1){var y=this.rangeList.ranges,_=y[y.length-1],b=a.fromPoints(y[0].start,_.end);this.toSingleRange(),this.setSelectionRange(b,_.cursor==_.start)}else{var E=this.session.documentToScreenPosition(this.cursor),x=this.session.documentToScreenPosition(this.anchor),O=this.rectangularRangeBlock(E,x);O.forEach(this.addRange,this)}},this.rectangularRangeBlock=function(y,_,b){var E=[],x=y.column<_.column;if(x)var O=y.column,M=_.column,k=y.offsetX,T=_.offsetX;else var O=_.column,M=y.column,k=_.offsetX,T=y.offsetX;var S=y.row<_.row;if(S)var w=y.row,L=_.row;else var w=_.row,L=y.row;O<0&&(O=0),w<0&&(w=0),w==L&&(b=!0);for(var q,A=w;A<=L;A++){var I=a.fromPoints(this.session.screenToDocumentPosition(A,O,k),this.session.screenToDocumentPosition(A,M,T));if(I.isEmpty()){if(q&&$(I.end,q))break;q=I.end}I.cursor=x?I.start:I.end,E.push(I)}if(S&&E.reverse(),!b){for(var F=E.length-1;E[F].isEmpty()&&F>0;)F--;if(F>0)for(var V=0;E[V].isEmpty();)V++;for(var R=F;R>=V;R--)E[R].isEmpty()&&E.splice(R,1)}return E}}.call(u.prototype);var p=e("./editor").Editor;(function(){this.updateSelectionMarkers=function(){this.renderer.updateCursor(),this.renderer.updateBackMarkers()},this.addSelectionMarker=function(y){y.cursor||(y.cursor=y.end);var _=this.getSelectionStyle();return y.marker=this.session.addMarker(y,"ace_selection",_),this.session.$selectionMarkers.push(y),this.session.selectionMarkerCount=this.session.$selectionMarkers.length,y},this.removeSelectionMarker=function(y){if(!!y.marker){this.session.removeMarker(y.marker);var _=this.session.$selectionMarkers.indexOf(y);_!=-1&&this.session.$selectionMarkers.splice(_,1),this.session.selectionMarkerCount=this.session.$selectionMarkers.length}},this.removeSelectionMarkers=function(y){for(var _=this.session.$selectionMarkers,b=y.length;b--;){var E=y[b];if(!!E.marker){this.session.removeMarker(E.marker);var x=_.indexOf(E);x!=-1&&_.splice(x,1)}}this.session.selectionMarkerCount=_.length},this.$onAddRange=function(y){this.addSelectionMarker(y.range),this.renderer.updateCursor(),this.renderer.updateBackMarkers()},this.$onRemoveRange=function(y){this.removeSelectionMarkers(y.ranges),this.renderer.updateCursor(),this.renderer.updateBackMarkers()},this.$onMultiSelect=function(y){this.inMultiSelectMode||(this.inMultiSelectMode=!0,this.setStyle("ace_multiselect"),this.keyBinding.addKeyboardHandler(n.keyboardHandler),this.commands.setDefaultHandler("exec",this.$onMultiSelectExec),this.renderer.updateCursor(),this.renderer.updateBackMarkers())},this.$onSingleSelect=function(y){this.session.multiSelect.inVirtualMode||(this.inMultiSelectMode=!1,this.unsetStyle("ace_multiselect"),this.keyBinding.removeKeyboardHandler(n.keyboardHandler),this.commands.removeDefaultHandler("exec",this.$onMultiSelectExec),this.renderer.updateCursor(),this.renderer.updateBackMarkers(),this._emit("changeSelection"))},this.$onMultiSelectExec=function(y){var _=y.command,b=y.editor;if(!!b.multiSelect){if(_.multiSelectAction)_.multiSelectAction=="forEach"?E=b.forEachSelection(_,y.args):_.multiSelectAction=="forEachLine"?E=b.forEachSelection(_,y.args,!0):_.multiSelectAction=="single"?(b.exitMultiSelectMode(),E=_.exec(b,y.args||{})):E=_.multiSelectAction(b,y.args||{});else{var E=_.exec(b,y.args||{});b.multiSelect.addRange(b.multiSelect.toOrientedRange()),b.multiSelect.mergeOverlappingRanges()}return E}},this.forEachSelection=function(y,_,b){if(!this.inVirtualSelectionMode){var E=b&&b.keepOrder,x=b==!0||b&&b.$byLines,O=this.session,M=this.selection,k=M.rangeList,T=(E?M:k).ranges,S;if(!T.length)return y.exec?y.exec(this,_||{}):y(this,_||{});var w=M._eventRegistry;M._eventRegistry={};var L=new u(O);this.inVirtualSelectionMode=!0;for(var q=T.length;q--;){if(x)for(;q>0&&T[q].start.row==T[q-1].end.row;)q--;L.fromOrientedRange(T[q]),L.index=q,this.selection=O.selection=L;var A=y.exec?y.exec(this,_||{}):y(this,_||{});!S&&A!==void 0&&(S=A),L.toOrientedRange(T[q])}L.detach(),this.selection=O.selection=M,this.inVirtualSelectionMode=!1,M._eventRegistry=w,M.mergeOverlappingRanges(),M.ranges[0]&&M.fromOrientedRange(M.ranges[0]);var I=this.renderer.$scrollAnimation;return this.onCursorChange(),this.onSelectionChange(),I&&I.from==I.to&&this.renderer.animateScrolling(I.from),S}},this.exitMultiSelectMode=function(){!this.inMultiSelectMode||this.inVirtualSelectionMode||this.multiSelect.toSingleRange()},this.getSelectedText=function(){var y="";if(this.inMultiSelectMode&&!this.inVirtualSelectionMode){for(var _=this.multiSelect.rangeList.ranges,b=[],E=0;E<_.length;E++)b.push(this.session.getTextRange(_[E]));var x=this.session.getDocument().getNewLineCharacter();y=b.join(x),y.length==(b.length-1)*x.length&&(y="")}else this.selection.isEmpty()||(y=this.session.getTextRange(this.getSelectionRange()));return y},this.$checkMultiselectChange=function(y,_){if(this.inMultiSelectMode&&!this.inVirtualSelectionMode){var b=this.multiSelect.ranges[0];if(this.multiSelect.isEmpty()&&_==this.multiSelect.anchor)return;var E=_==this.multiSelect.anchor?b.cursor==b.start?b.end:b.start:b.cursor;E.row!=_.row||this.session.$clipPositionToDocument(E.row,E.column).column!=_.column?this.multiSelect.toSingleRange(this.multiSelect.toOrientedRange()):this.multiSelect.mergeOverlappingRanges()}},this.findAll=function(y,_,b){if(_=_||{},_.needle=y||_.needle,_.needle==null){var E=this.selection.isEmpty()?this.selection.getWordRange():this.selection.getRange();_.needle=this.session.getTextRange(E)}this.$search.set(_);var x=this.$search.findAll(this.session);if(!x.length)return 0;var O=this.multiSelect;b||O.toSingleRange(x[0]);for(var M=x.length;M--;)O.addRange(x[M],!0);return E&&O.rangeList.rangeAtPoint(E.start)&&O.addRange(E,!0),x.length},this.selectMoreLines=function(y,_){var b=this.selection.toOrientedRange(),E=b.cursor==b.end,x=this.session.documentToScreenPosition(b.cursor);this.selection.$desiredColumn&&(x.column=this.selection.$desiredColumn);var O=this.session.screenToDocumentPosition(x.row+y,x.column);if(b.isEmpty())var k=O;else var M=this.session.documentToScreenPosition(E?b.end:b.start),k=this.session.screenToDocumentPosition(M.row+y,M.column);if(E){var T=a.fromPoints(O,k);T.cursor=T.start}else{var T=a.fromPoints(k,O);T.cursor=T.end}if(T.desiredColumn=x.column,!this.selection.inMultiSelectMode)this.selection.addRange(b);else if(_)var S=b.cursor;this.selection.addRange(T),S&&this.selection.substractPoint(S)},this.transposeSelections=function(y){for(var _=this.session,b=_.multiSelect,E=b.ranges,x=E.length;x--;){var O=E[x];if(O.isEmpty()){var M=_.getWordRange(O.start.row,O.start.column);O.start.row=M.start.row,O.start.column=M.start.column,O.end.row=M.end.row,O.end.column=M.end.column}}b.mergeOverlappingRanges();for(var k=[],x=E.length;x--;){var O=E[x];k.unshift(_.getTextRange(O))}y<0?k.unshift(k.pop()):k.push(k.shift());for(var x=E.length;x--;){var O=E[x],T=O.clone();_.replace(O,k[x]),O.start.row=T.start.row,O.start.column=T.start.column}b.fromOrientedRange(b.ranges[0])},this.selectMore=function(y,_,b){var E=this.session,x=E.multiSelect,O=x.toOrientedRange();if(!(O.isEmpty()&&(O=E.getWordRange(O.start.row,O.start.column),O.cursor=y==-1?O.start:O.end,this.multiSelect.addRange(O),b))){var M=E.getTextRange(O),k=s(E,M,y);k&&(k.cursor=y==-1?k.start:k.end,this.session.unfold(k),this.multiSelect.addRange(k),this.renderer.scrollCursorIntoView(null,.5)),_&&this.multiSelect.substractPoint(O.cursor)}},this.alignCursors=function(){var y=this.session,_=y.multiSelect,b=_.ranges,E=-1,x=b.filter(function(F){if(F.cursor.row==E)return!0;E=F.cursor.row});if(!b.length||x.length==b.length-1){var O=this.selection.getRange(),M=O.start.row,k=O.end.row,T=M==k;if(T){var S=this.session.getLength(),w;do w=this.session.getLine(k);while(/[=:]/.test(w)&&++k0);M<0&&(M=0),k>=S&&(k=S-1)}var L=this.session.removeFullLines(M,k);L=this.$reAlignText(L,T),this.session.insert({row:M,column:0},L.join(` +`)+` +`),T||(O.start.column=0,O.end.column=L[L.length-1].length),this.selection.setRange(O)}else{x.forEach(function(F){_.substractPoint(F.cursor)});var q=0,A=1/0,I=b.map(function(F){var V=F.cursor,R=y.getLine(V.row),B=R.substr(V.column).search(/\S/g);return B==-1&&(B=0),V.column>q&&(q=V.column),BN?y.insert(R,l.stringRepeat(" ",B-N)):y.remove(new a(R.row,R.column,R.row,R.column-B+N)),F.start.column=F.end.column=q,F.start.row=F.end.row=R.row,F.cursor=F.end}),_.fromOrientedRange(b[0]),this.renderer.updateCursor(),this.renderer.updateBackMarkers()}},this.$reAlignText=function(y,_){var b=!0,E=!0,x,O,M;return y.map(function(L){var q=L.match(/(\s*)(.*?)(\s*)([=:].*)/);return q?x==null?(x=q[1].length,O=q[2].length,M=q[3].length,q):(x+O+M!=q[1].length+q[2].length+q[3].length&&(E=!1),x!=q[1].length&&(b=!1),x>q[1].length&&(x=q[1].length),Oq[3].length&&(M=q[3].length),q):[L]}).map(_?T:b?E?S:T:w);function k(L){return l.stringRepeat(" ",L)}function T(L){return L[2]?k(x)+L[2]+k(O-L[2].length+M)+L[4].replace(/^([=:])\s+/,"$1 "):L[0]}function S(L){return L[2]?k(x+O-L[2].length)+L[2]+k(M)+L[4].replace(/^([=:])\s+/,"$1 "):L[0]}function w(L){return L[2]?k(x)+L[2]+k(M)+L[4].replace(/^([=:])\s+/,"$1 "):L[0]}}}).call(p.prototype);function $(y,_){return y.row==_.row&&y.column==_.column}h.onSessionChange=function(y){var _=y.session;_&&!_.multiSelect&&(_.$selectionMarkers=[],_.selection.$initRangeList(),_.multiSelect=_.selection),this.multiSelect=_&&_.multiSelect;var b=y.oldSession;b&&(b.multiSelect.off("addRange",this.$onAddRange),b.multiSelect.off("removeRange",this.$onRemoveRange),b.multiSelect.off("multiSelect",this.$onMultiSelect),b.multiSelect.off("singleSelect",this.$onSingleSelect),b.multiSelect.lead.off("change",this.$checkMultiselectChange),b.multiSelect.anchor.off("change",this.$checkMultiselectChange)),_&&(_.multiSelect.on("addRange",this.$onAddRange),_.multiSelect.on("removeRange",this.$onRemoveRange),_.multiSelect.on("multiSelect",this.$onMultiSelect),_.multiSelect.on("singleSelect",this.$onSingleSelect),_.multiSelect.lead.on("change",this.$checkMultiselectChange),_.multiSelect.anchor.on("change",this.$checkMultiselectChange)),_&&this.inMultiSelectMode!=_.selection.inMultiSelectMode&&(_.selection.inMultiSelectMode?this.$onMultiSelect():this.$onSingleSelect())};function v(y){y.$multiselectOnSessionChange||(y.$onAddRange=y.$onAddRange.bind(y),y.$onRemoveRange=y.$onRemoveRange.bind(y),y.$onMultiSelect=y.$onMultiSelect.bind(y),y.$onSingleSelect=y.$onSingleSelect.bind(y),y.$multiselectOnSessionChange=h.onSessionChange.bind(y),y.$checkMultiselectChange=y.$checkMultiselectChange.bind(y),y.$multiselectOnSessionChange(y),y.on("changeSession",y.$multiselectOnSessionChange),y.on("mousedown",r),y.commands.addCommands(n.defaultCommands),C(y))}function C(y){if(!y.textInput)return;var _=y.textInput.getElement(),b=!1;f.addListener(_,"keydown",function(x){var O=x.keyCode==18&&!(x.ctrlKey||x.shiftKey||x.metaKey);y.$blockSelectEnabled&&O?b||(y.renderer.setMouseCursor("crosshair"),b=!0):b&&E()},y),f.addListener(_,"keyup",E,y),f.addListener(_,"blur",E,y);function E(x){b&&(y.renderer.setMouseCursor(""),b=!1)}}h.MultiSelect=v,e("./config").defineOptions(p.prototype,"editor",{enableMultiselect:{set:function(y){v(this),y?this.on("mousedown",r):this.off("mousedown",r)},value:!0},enableBlockSelect:{set:function(y){this.$blockSelectEnabled=y},value:!0}})}),ace.define("ace/mode/folding/fold_mode",["require","exports","module","ace/range"],function(e,h,m){var g=e("../../range").Range,a=h.FoldMode=function(){};(function(){this.foldingStartMarker=null,this.foldingStopMarker=null,this.getFoldWidget=function(u,r,f){var l=u.getLine(f);return this.foldingStartMarker.test(l)?"start":r=="markbeginend"&&this.foldingStopMarker&&this.foldingStopMarker.test(l)?"end":""},this.getFoldWidgetRange=function(u,r,f){return null},this.indentationBlock=function(u,r,f){var l=/\S/,n=u.getLine(r),i=n.search(l);if(i!=-1){for(var o=f||n.length,s=u.getLength(),c=r,p=r;++rc){var C=u.getLine(p).length;return new g(c,o,p,C)}}},this.openingBracketBlock=function(u,r,f,l,n){var i={row:f,column:l+1},o=u.$findClosingBracket(r,i,n);if(!!o){var s=u.foldWidgets[o.row];return s==null&&(s=u.getFoldWidget(o.row)),s=="start"&&o.row>i.row&&(o.row--,o.column=u.getLine(o.row).length),g.fromPoints(i,o)}},this.closingBracketBlock=function(u,r,f,l,n){var i={row:f,column:l},o=u.$findOpeningBracket(r,i);if(!!o)return o.column++,i.column--,g.fromPoints(o,i)}}).call(a.prototype)}),ace.define("ace/ext/error_marker",["require","exports","module","ace/line_widgets","ace/lib/dom","ace/range","ace/config"],function(e,h,m){var g=e("../line_widgets").LineWidgets,a=e("../lib/dom"),u=e("../range").Range,r=e("../config").nls;function f(n,i,o){for(var s=0,c=n.length-1;s<=c;){var p=s+c>>1,$=o(i,n[p]);if($>0)s=p+1;else if($<0)c=p-1;else return p}return-(s+1)}function l(n,i,o){var s=n.getAnnotations().sort(u.comparePoints);if(!!s.length){var c=f(s,{row:i,column:-1},u.comparePoints);c<0&&(c=-c-1),c>=s.length?c=o>0?0:s.length-1:c===0&&o<0&&(c=s.length-1);var p=s[c];if(!(!p||!o)){if(p.row===i){do p=s[c+=o];while(p&&p.row===i);if(!p)return s.slice()}var $=[];i=p.row;do $[o<0?"unshift":"push"](p),p=s[c+=o];while(p&&p.row==i);return $.length&&$}}}h.showErrorMarker=function(n,i){var o=n.session;o.widgetManager||(o.widgetManager=new g(o),o.widgetManager.attach(n));var s=n.getCursorPosition(),c=s.row,p=o.widgetManager.getWidgetsAtRow(c).filter(function(O){return O.type=="errorMarker"})[0];p?p.destroy():c-=i;var $=l(o,c,i),v;if($){var C=$[0];s.column=(C.pos&&typeof C.column!="number"?C.pos.sc:C.column)||0,s.row=C.row,v=n.renderer.$gutterLayer.$annotations[s.row]}else{if(p)return;v={text:[r("Looks good!")],className:"ace_ok"}}n.session.unfold(s.row),n.selection.moveToPosition(s);var y={row:s.row,fixedWidth:!0,coverGutter:!0,el:a.createElement("div"),type:"errorMarker"},_=y.el.appendChild(a.createElement("div")),b=y.el.appendChild(a.createElement("div"));b.className="error_widget_arrow "+v.className;var E=n.renderer.$cursorLayer.getPixelPosition(s).left;b.style.left=E+n.renderer.gutterWidth-5+"px",y.el.className="error_widget_wrapper",_.className="error_widget "+v.className,_.innerHTML=v.text.join("
"),_.appendChild(a.createElement("div"));var x=function(O,M,k){if(M===0&&(k==="esc"||k==="return"))return y.destroy(),{command:"null"}};y.destroy=function(){n.$mouseHandler.isMousePressed||(n.keyBinding.removeKeyboardHandler(x),o.widgetManager.removeLineWidget(y),n.off("changeSelection",y.destroy),n.off("changeSession",y.destroy),n.off("mouseup",y.destroy),n.off("change",y.destroy))},n.keyBinding.addKeyboardHandler(x),n.on("changeSelection",y.destroy),n.on("changeSession",y.destroy),n.on("mouseup",y.destroy),n.on("change",y.destroy),n.session.widgetManager.addLineWidget(y),y.el.onmousedown=n.focus.bind(n),n.renderer.scrollCursorIntoView(null,.5,{bottom:y.el.offsetHeight})},a.importCssString(` + .error_widget_wrapper { + background: inherit; + color: inherit; + border:none + } + .error_widget { + border-top: solid 2px; + border-bottom: solid 2px; + margin: 5px 0; + padding: 10px 40px; + white-space: pre-wrap; + } + .error_widget.ace_error, .error_widget_arrow.ace_error{ + border-color: #ff5a5a + } + .error_widget.ace_warning, .error_widget_arrow.ace_warning{ + border-color: #F1D817 + } + .error_widget.ace_info, .error_widget_arrow.ace_info{ + border-color: #5a5a5a + } + .error_widget.ace_ok, .error_widget_arrow.ace_ok{ + border-color: #5aaa5a + } + .error_widget_arrow { + position: absolute; + border: solid 5px; + border-top-color: transparent!important; + border-right-color: transparent!important; + border-left-color: transparent!important; + top: -5px; + } +`,"error_marker.css",!1)}),ace.define("ace/ace",["require","exports","module","ace/lib/dom","ace/range","ace/editor","ace/edit_session","ace/undomanager","ace/virtual_renderer","ace/worker/worker_client","ace/keyboard/hash_handler","ace/placeholder","ace/multi_select","ace/mode/folding/fold_mode","ace/theme/textmate","ace/ext/error_marker","ace/config","ace/loader_build"],function(e,h,m){e("./loader_build")(h);var g=e("./lib/dom"),a=e("./range").Range,u=e("./editor").Editor,r=e("./edit_session").EditSession,f=e("./undomanager").UndoManager,l=e("./virtual_renderer").VirtualRenderer;e("./worker/worker_client"),e("./keyboard/hash_handler"),e("./placeholder"),e("./multi_select"),e("./mode/folding/fold_mode"),e("./theme/textmate"),e("./ext/error_marker"),h.config=e("./config"),h.edit=function(n,i){if(typeof n=="string"){var o=n;if(n=document.getElementById(o),!n)throw new Error("ace.edit can't find div #"+o)}if(n&&n.env&&n.env.editor instanceof u)return n.env.editor;var s="";if(n&&/input|textarea/i.test(n.tagName)){var c=n;s=c.value,n=g.createElement("pre"),c.parentNode.replaceChild(n,c)}else n&&(s=n.textContent,n.innerHTML="");var p=h.createEditSession(s),$=new u(new l(n),p,i),v={document:p,editor:$,onResize:$.resize.bind($,null)};return c&&(v.textarea=c),$.on("destroy",function(){v.editor.container.env=null}),$.container.env=$.env=v,$},h.createEditSession=function(n,i){var o=new r(n,i);return o.setUndoManager(new f),o},h.Range=a,h.Editor=u,h.EditSession=r,h.UndoManager=f,h.VirtualRenderer=l,h.version=h.config.version}),function(){ace.require(["ace/ace"],function(e){e&&(e.config.init(!0),e.define=ace.define);var h=function(){return this}();!h&&typeof window!="undefined"&&(h=window),!h&&typeof self!="undefined"&&(h=self),h.ace||(h.ace=e);for(var m in e)e.hasOwnProperty(m)&&(h.ace[m]=e[m]);h.ace.default=h.ace,t&&(t.exports=h.ace)})}()})(ace$2);var ace$1=ace$2.exports,themeSqlserver={exports:{}};(function(t,d){ace.define("ace/theme/sqlserver-css",["require","exports","module"],function(e,h,m){m.exports=`.ace-sqlserver .ace_gutter { + background: #ebebeb; + color: #333; + overflow: hidden; +} + +.ace-sqlserver .ace_print-margin { + width: 1px; + background: #e8e8e8; +} + +.ace-sqlserver { + background-color: #FFFFFF; + color: black; +} + +.ace-sqlserver .ace_identifier { + color: black; +} + +.ace-sqlserver .ace_keyword { + color: #0000FF; +} + +.ace-sqlserver .ace_numeric { + color: black; +} + +.ace-sqlserver .ace_storage { + color: #11B7BE; +} + +.ace-sqlserver .ace_keyword.ace_operator, +.ace-sqlserver .ace_lparen, +.ace-sqlserver .ace_rparen, +.ace-sqlserver .ace_punctuation { + color: #808080; +} + +.ace-sqlserver .ace_set.ace_statement { + color: #0000FF; + text-decoration: underline; +} + +.ace-sqlserver .ace_cursor { + color: black; +} + +.ace-sqlserver .ace_invisible { + color: rgb(191, 191, 191); +} + +.ace-sqlserver .ace_constant.ace_buildin { + color: rgb(88, 72, 246); +} + +.ace-sqlserver .ace_constant.ace_language { + color: #979797; +} + +.ace-sqlserver .ace_constant.ace_library { + color: rgb(6, 150, 14); +} + +.ace-sqlserver .ace_invalid { + background-color: rgb(153, 0, 0); + color: white; +} + +.ace-sqlserver .ace_support.ace_function { + color: #FF00FF; +} + +.ace-sqlserver .ace_support.ace_constant { + color: rgb(6, 150, 14); +} + +.ace-sqlserver .ace_class { + color: #008080; +} + +.ace-sqlserver .ace_support.ace_other { + color: #6D79DE; +} + +.ace-sqlserver .ace_variable.ace_parameter { + font-style: italic; + color: #FD971F; +} + +.ace-sqlserver .ace_comment { + color: #008000; +} + +.ace-sqlserver .ace_constant.ace_numeric { + color: black; +} + +.ace-sqlserver .ace_variable { + color: rgb(49, 132, 149); +} + +.ace-sqlserver .ace_xml-pe { + color: rgb(104, 104, 91); +} + +.ace-sqlserver .ace_support.ace_storedprocedure { + color: #800000; +} + +.ace-sqlserver .ace_heading { + color: rgb(12, 7, 255); +} + +.ace-sqlserver .ace_list { + color: rgb(185, 6, 144); +} + +.ace-sqlserver .ace_marker-layer .ace_selection { + background: rgb(181, 213, 255); +} + +.ace-sqlserver .ace_marker-layer .ace_step { + background: rgb(252, 255, 0); +} + +.ace-sqlserver .ace_marker-layer .ace_stack { + background: rgb(164, 229, 101); +} + +.ace-sqlserver .ace_marker-layer .ace_bracket { + margin: -1px 0 0 -1px; + border: 1px solid rgb(192, 192, 192); +} + +.ace-sqlserver .ace_marker-layer .ace_active-line { + background: rgba(0, 0, 0, 0.07); +} + +.ace-sqlserver .ace_gutter-active-line { + background-color: #dcdcdc; +} + +.ace-sqlserver .ace_marker-layer .ace_selected-word { + background: rgb(250, 250, 255); + border: 1px solid rgb(200, 200, 250); +} + +.ace-sqlserver .ace_meta.ace_tag { + color: #0000FF; +} + +.ace-sqlserver .ace_string.ace_regex { + color: #FF0000; +} + +.ace-sqlserver .ace_string { + color: #FF0000; +} + +.ace-sqlserver .ace_entity.ace_other.ace_attribute-name { + color: #994409; +} + +.ace-sqlserver .ace_indent-guide { + background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAE0lEQVQImWP4////f4bLly//BwAmVgd1/w11/gAAAABJRU5ErkJggg==") right repeat-y; +} + +.ace-sqlserver .ace_indent-guide-active { + background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAIGNIUk0AAHolAACAgwAA+f8AAIDpAAB1MAAA6mAAADqYAAAXb5JfxUYAAAAZSURBVHjaYvj///9/hivKyv8BAAAA//8DACLqBhbvk+/eAAAAAElFTkSuQmCC") right repeat-y; +} +`}),ace.define("ace/theme/sqlserver",["require","exports","module","ace/theme/sqlserver-css","ace/lib/dom"],function(e,h,m){h.isDark=!1,h.cssClass="ace-sqlserver",h.cssText=e("./sqlserver-css");var g=e("../lib/dom");g.importCssString(h.cssText,h.cssClass,!1)}),function(){ace.require(["ace/theme/sqlserver"],function(e){t&&(t.exports=e)})}()})(themeSqlserver);var modeJavascript={exports:{}};(function(t,d){ace.define("ace/mode/jsdoc_comment_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(e,h,m){var g=e("../lib/oop"),a=e("./text_highlight_rules").TextHighlightRules,u=function(){this.$rules={start:[{token:["comment.doc.tag","comment.doc.text","lparen.doc"],regex:"(@(?:param|member|typedef|property|namespace|var|const|callback))(\\s*)({)",push:[{token:"lparen.doc",regex:"{",push:[{include:"doc-syntax"},{token:"rparen.doc",regex:"}|(?=$)",next:"pop"}]},{token:["rparen.doc","text.doc","variable.parameter.doc","lparen.doc","variable.parameter.doc","rparen.doc"],regex:/(})(\s*)(?:([\w=:\/\.]+)|(?:(\[)([\w=:\/\.]+)(\])))/,next:"pop"},{token:"rparen.doc",regex:"}|(?=$)",next:"pop"},{include:"doc-syntax"},{defaultToken:"text.doc"}]},{token:["comment.doc.tag","text.doc","lparen.doc"],regex:"(@(?:returns?|yields|type|this|suppress|public|protected|private|package|modifies|implements|external|exception|throws|enum|define|extends))(\\s*)({)",push:[{token:"lparen.doc",regex:"{",push:[{include:"doc-syntax"},{token:"rparen.doc",regex:"}|(?=$)",next:"pop"}]},{token:"rparen.doc",regex:"}|(?=$)",next:"pop"},{include:"doc-syntax"},{defaultToken:"text.doc"}]},{token:["comment.doc.tag","text.doc","variable.parameter.doc"],regex:'(@(?:alias|memberof|instance|module|name|lends|namespace|external|this|template|requires|param|implements|function|extends|typedef|mixes|constructor|var|memberof\\!|event|listens|exports|class|constructs|interface|emits|fires|throws|const|callback|borrows|augments))(\\s+)(\\w[\\w#.:/~"\\-]*)?'},{token:["comment.doc.tag","text.doc","variable.parameter.doc"],regex:"(@method)(\\s+)(\\w[\\w.\\(\\)]*)"},{token:"comment.doc.tag",regex:"@access\\s+(?:private|public|protected)"},{token:"comment.doc.tag",regex:"@kind\\s+(?:class|constant|event|external|file|function|member|mixin|module|namespace|typedef)"},{token:"comment.doc.tag",regex:"@\\w+(?=\\s|$)"},u.getTagRule(),{defaultToken:"comment.doc",caseInsensitive:!0}],"doc-syntax":[{token:"operator.doc",regex:/[|:]/},{token:"paren.doc",regex:/[\[\]]/}]},this.normalizeRules()};g.inherits(u,a),u.getTagRule=function(r){return{token:"comment.doc.tag.storage.type",regex:"\\b(?:TODO|FIXME|XXX|HACK)\\b"}},u.getStartRule=function(r){return{token:"comment.doc",regex:"\\/\\*(?=\\*)",next:r}},u.getEndRule=function(r){return{token:"comment.doc",regex:"\\*\\/",next:r}},h.JsDocCommentHighlightRules=u}),ace.define("ace/mode/javascript_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/jsdoc_comment_highlight_rules","ace/mode/text_highlight_rules"],function(e,h,m){function g(){var i=l.replace("\\d","\\d\\-"),o={onMatch:function(c,p,$){var v=c.charAt(1)=="/"?2:1;return v==1?(p!=this.nextState?$.unshift(this.next,this.nextState,0):$.unshift(this.next),$[2]++):v==2&&p==this.nextState&&($[1]--,(!$[1]||$[1]<0)&&($.shift(),$.shift())),[{type:"meta.tag.punctuation."+(v==1?"":"end-")+"tag-open.xml",value:c.slice(0,v)},{type:"meta.tag.tag-name.xml",value:c.substr(v)}]},regex:"",onMatch:function(c,p,$){return p==$[0]&&$.shift(),c.length==2&&($[0]==this.nextState&&$[1]--,(!$[1]||$[1]<0)&&$.splice(0,2)),this.next=$[0]||"start",[{type:this.token,value:c}]},nextState:"jsx"},s,a("jsxAttributes"),{token:"entity.other.attribute-name.xml",regex:i},{token:"keyword.operator.attribute-equals.xml",regex:"="},{token:"text.tag-whitespace.xml",regex:"\\s+"},{token:"string.attribute-value.xml",regex:"'",stateName:"jsx_attr_q",push:[{token:"string.attribute-value.xml",regex:"'",next:"pop"},{include:"reference"},{defaultToken:"string.attribute-value.xml"}]},{token:"string.attribute-value.xml",regex:'"',stateName:"jsx_attr_qq",push:[{token:"string.attribute-value.xml",regex:'"',next:"pop"},{include:"reference"},{defaultToken:"string.attribute-value.xml"}]},o],this.$rules.reference=[{token:"constant.language.escape.reference.xml",regex:"(?:&#[0-9]+;)|(?:&#x[0-9a-fA-F]+;)|(?:&[a-zA-Z0-9_:\\.-]+;)"}]}function a(i){return[{token:"comment",regex:/\/\*/,next:[r.getTagRule(),{token:"comment",regex:"\\*\\/",next:i||"pop"},{defaultToken:"comment",caseInsensitive:!0}]},{token:"comment",regex:"\\/\\/",next:[r.getTagRule(),{token:"comment",regex:"$|^",next:i||"pop"},{defaultToken:"comment",caseInsensitive:!0}]}]}var u=e("../lib/oop"),r=e("./jsdoc_comment_highlight_rules").JsDocCommentHighlightRules,f=e("./text_highlight_rules").TextHighlightRules,l="[a-zA-Z\\$_\xA1-\uFFFF][a-zA-Z\\d\\$_\xA1-\uFFFF]*",n=function(i){var o=this.createKeywordMapper({"variable.language":"Array|Boolean|Date|Function|Iterator|Number|Object|RegExp|String|Proxy|Symbol|Namespace|QName|XML|XMLList|ArrayBuffer|Float32Array|Float64Array|Int16Array|Int32Array|Int8Array|Uint16Array|Uint32Array|Uint8Array|Uint8ClampedArray|Error|EvalError|InternalError|RangeError|ReferenceError|StopIteration|SyntaxError|TypeError|URIError|decodeURI|decodeURIComponent|encodeURI|encodeURIComponent|eval|isFinite|isNaN|parseFloat|parseInt|JSON|Math|this|arguments|prototype|window|document",keyword:"const|yield|import|get|set|async|await|break|case|catch|continue|default|delete|do|else|finally|for|function|if|in|of|instanceof|new|return|switch|throw|try|typeof|let|var|while|with|debugger|__parent__|__count__|escape|unescape|with|__proto__|class|enum|extends|super|export|implements|private|public|interface|package|protected|static|constructor","storage.type":"const|let|var|function","constant.language":"null|Infinity|NaN|undefined","support.function":"alert","constant.language.boolean":"true|false"},"identifier"),s="case|do|else|finally|in|instanceof|return|throw|try|typeof|yield|void",c="\\\\(?:x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|u{[0-9a-fA-F]{1,6}}|[0-2][0-7]{0,2}|3[0-7][0-7]?|[4-7][0-7]?|.)";this.$rules={no_regex:[r.getStartRule("doc-start"),a("no_regex"),{token:"string",regex:"'(?=.)",next:"qstring"},{token:"string",regex:'"(?=.)',next:"qqstring"},{token:"constant.numeric",regex:/0(?:[xX][0-9a-fA-F]+|[oO][0-7]+|[bB][01]+)\b/},{token:"constant.numeric",regex:/(?:\d\d*(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+\b)?/},{token:["storage.type","punctuation.operator","support.function","punctuation.operator","entity.name.function","text","keyword.operator"],regex:"("+l+")(\\.)(prototype)(\\.)("+l+")(\\s*)(=)",next:"function_arguments"},{token:["storage.type","punctuation.operator","entity.name.function","text","keyword.operator","text","storage.type","text","paren.lparen"],regex:"("+l+")(\\.)("+l+")(\\s*)(=)(\\s*)(function\\*?)(\\s*)(\\()",next:"function_arguments"},{token:["entity.name.function","text","keyword.operator","text","storage.type","text","paren.lparen"],regex:"("+l+")(\\s*)(=)(\\s*)(function\\*?)(\\s*)(\\()",next:"function_arguments"},{token:["storage.type","punctuation.operator","entity.name.function","text","keyword.operator","text","storage.type","text","entity.name.function","text","paren.lparen"],regex:"("+l+")(\\.)("+l+")(\\s*)(=)(\\s*)(function\\*?)(\\s+)(\\w+)(\\s*)(\\()",next:"function_arguments"},{token:["storage.type","text","entity.name.function","text","paren.lparen"],regex:"(function\\*?)(\\s+)("+l+")(\\s*)(\\()",next:"function_arguments"},{token:["entity.name.function","text","punctuation.operator","text","storage.type","text","paren.lparen"],regex:"("+l+")(\\s*)(:)(\\s*)(function\\*?)(\\s*)(\\()",next:"function_arguments"},{token:["text","text","storage.type","text","paren.lparen"],regex:"(:)(\\s*)(function\\*?)(\\s*)(\\()",next:"function_arguments"},{token:"keyword",regex:`from(?=\\s*('|"))`},{token:"keyword",regex:"(?:"+s+")\\b",next:"start"},{token:"support.constant",regex:/that\b/},{token:["storage.type","punctuation.operator","support.function.firebug"],regex:/(console)(\.)(warn|info|log|error|debug|time|trace|timeEnd|assert)\b/},{token:o,regex:l},{token:"punctuation.operator",regex:/[.](?![.])/,next:"property"},{token:"storage.type",regex:/=>/,next:"start"},{token:"keyword.operator",regex:/--|\+\+|\.{3}|===|==|=|!=|!==|<+=?|>+=?|!|&&|\|\||\?:|[!$%&*+\-~\/^]=?/,next:"start"},{token:"punctuation.operator",regex:/[?:,;.]/,next:"start"},{token:"paren.lparen",regex:/[\[({]/,next:"start"},{token:"paren.rparen",regex:/[\])}]/},{token:"comment",regex:/^#!.*$/}],property:[{token:"text",regex:"\\s+"},{token:["storage.type","punctuation.operator","entity.name.function","text","keyword.operator","text","storage.type","text","entity.name.function","text","paren.lparen"],regex:"("+l+")(\\.)("+l+")(\\s*)(=)(\\s*)(function\\*?)(?:(\\s+)(\\w+))?(\\s*)(\\()",next:"function_arguments"},{token:"punctuation.operator",regex:/[.](?![.])/},{token:"support.function",regex:/(s(?:h(?:ift|ow(?:Mod(?:elessDialog|alDialog)|Help))|croll(?:X|By(?:Pages|Lines)?|Y|To)?|t(?:op|rike)|i(?:n|zeToContent|debar|gnText)|ort|u(?:p|b(?:str(?:ing)?)?)|pli(?:ce|t)|e(?:nd|t(?:Re(?:sizable|questHeader)|M(?:i(?:nutes|lliseconds)|onth)|Seconds|Ho(?:tKeys|urs)|Year|Cursor|Time(?:out)?|Interval|ZOptions|Date|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Date|FullYear)|FullYear|Active)|arch)|qrt|lice|avePreferences|mall)|h(?:ome|andleEvent)|navigate|c(?:har(?:CodeAt|At)|o(?:s|n(?:cat|textual|firm)|mpile)|eil|lear(?:Timeout|Interval)?|a(?:ptureEvents|ll)|reate(?:StyleSheet|Popup|EventObject))|t(?:o(?:GMTString|S(?:tring|ource)|U(?:TCString|pperCase)|Lo(?:caleString|werCase))|est|a(?:n|int(?:Enabled)?))|i(?:s(?:NaN|Finite)|ndexOf|talics)|d(?:isableExternalCapture|ump|etachEvent)|u(?:n(?:shift|taint|escape|watch)|pdateCommands)|j(?:oin|avaEnabled)|p(?:o(?:p|w)|ush|lugins.refresh|a(?:ddings|rse(?:Int|Float)?)|r(?:int|ompt|eference))|e(?:scape|nableExternalCapture|val|lementFromPoint|x(?:p|ec(?:Script|Command)?))|valueOf|UTC|queryCommand(?:State|Indeterm|Enabled|Value)|f(?:i(?:nd|lter|le(?:ModifiedDate|Size|CreatedDate|UpdatedDate)|xed)|o(?:nt(?:size|color)|rward|rEach)|loor|romCharCode)|watch|l(?:ink|o(?:ad|g)|astIndexOf)|a(?:sin|nchor|cos|t(?:tachEvent|ob|an(?:2)?)|pply|lert|b(?:s|ort))|r(?:ou(?:nd|teEvents)|e(?:size(?:By|To)|calc|turnValue|place|verse|l(?:oad|ease(?:Capture|Events)))|andom)|g(?:o|et(?:ResponseHeader|M(?:i(?:nutes|lliseconds)|onth)|Se(?:conds|lection)|Hours|Year|Time(?:zoneOffset)?|Da(?:y|te)|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Da(?:y|te)|FullYear)|FullYear|A(?:ttention|llResponseHeaders)))|m(?:in|ove(?:B(?:y|elow)|To(?:Absolute)?|Above)|ergeAttributes|a(?:tch|rgins|x))|b(?:toa|ig|o(?:ld|rderWidths)|link|ack))\b(?=\()/},{token:"support.function.dom",regex:/(s(?:ub(?:stringData|mit)|plitText|e(?:t(?:NamedItem|Attribute(?:Node)?)|lect))|has(?:ChildNodes|Feature)|namedItem|c(?:l(?:ick|o(?:se|neNode))|reate(?:C(?:omment|DATASection|aption)|T(?:Head|extNode|Foot)|DocumentFragment|ProcessingInstruction|E(?:ntityReference|lement)|Attribute))|tabIndex|i(?:nsert(?:Row|Before|Cell|Data)|tem)|open|delete(?:Row|C(?:ell|aption)|T(?:Head|Foot)|Data)|focus|write(?:ln)?|a(?:dd|ppend(?:Child|Data))|re(?:set|place(?:Child|Data)|move(?:NamedItem|Child|Attribute(?:Node)?)?)|get(?:NamedItem|Element(?:sBy(?:Name|TagName|ClassName)|ById)|Attribute(?:Node)?)|blur)\b(?=\()/},{token:"support.constant",regex:/(s(?:ystemLanguage|cr(?:ipts|ollbars|een(?:X|Y|Top|Left))|t(?:yle(?:Sheets)?|atus(?:Text|bar)?)|ibling(?:Below|Above)|ource|uffixes|e(?:curity(?:Policy)?|l(?:ection|f)))|h(?:istory|ost(?:name)?|as(?:h|Focus))|y|X(?:MLDocument|SLDocument)|n(?:ext|ame(?:space(?:s|URI)|Prop))|M(?:IN_VALUE|AX_VALUE)|c(?:haracterSet|o(?:n(?:structor|trollers)|okieEnabled|lorDepth|mp(?:onents|lete))|urrent|puClass|l(?:i(?:p(?:boardData)?|entInformation)|osed|asses)|alle(?:e|r)|rypto)|t(?:o(?:olbar|p)|ext(?:Transform|Indent|Decoration|Align)|ags)|SQRT(?:1_2|2)|i(?:n(?:ner(?:Height|Width)|put)|ds|gnoreCase)|zIndex|o(?:scpu|n(?:readystatechange|Line)|uter(?:Height|Width)|p(?:sProfile|ener)|ffscreenBuffering)|NEGATIVE_INFINITY|d(?:i(?:splay|alog(?:Height|Top|Width|Left|Arguments)|rectories)|e(?:scription|fault(?:Status|Ch(?:ecked|arset)|View)))|u(?:ser(?:Profile|Language|Agent)|n(?:iqueID|defined)|pdateInterval)|_content|p(?:ixelDepth|ort|ersonalbar|kcs11|l(?:ugins|atform)|a(?:thname|dding(?:Right|Bottom|Top|Left)|rent(?:Window|Layer)?|ge(?:X(?:Offset)?|Y(?:Offset)?))|r(?:o(?:to(?:col|type)|duct(?:Sub)?|mpter)|e(?:vious|fix)))|e(?:n(?:coding|abledPlugin)|x(?:ternal|pando)|mbeds)|v(?:isibility|endor(?:Sub)?|Linkcolor)|URLUnencoded|P(?:I|OSITIVE_INFINITY)|f(?:ilename|o(?:nt(?:Size|Family|Weight)|rmName)|rame(?:s|Element)|gColor)|E|whiteSpace|l(?:i(?:stStyleType|n(?:eHeight|kColor))|o(?:ca(?:tion(?:bar)?|lName)|wsrc)|e(?:ngth|ft(?:Context)?)|a(?:st(?:M(?:odified|atch)|Index|Paren)|yer(?:s|X)|nguage))|a(?:pp(?:MinorVersion|Name|Co(?:deName|re)|Version)|vail(?:Height|Top|Width|Left)|ll|r(?:ity|guments)|Linkcolor|bove)|r(?:ight(?:Context)?|e(?:sponse(?:XML|Text)|adyState))|global|x|m(?:imeTypes|ultiline|enubar|argin(?:Right|Bottom|Top|Left))|L(?:N(?:10|2)|OG(?:10E|2E))|b(?:o(?:ttom|rder(?:Width|RightWidth|BottomWidth|Style|Color|TopWidth|LeftWidth))|ufferDepth|elow|ackground(?:Color|Image)))\b/},{token:"identifier",regex:l},{regex:"",token:"empty",next:"no_regex"}],start:[r.getStartRule("doc-start"),a("start"),{token:"string.regexp",regex:"\\/",next:"regex"},{token:"text",regex:"\\s+|^$",next:"start"},{token:"empty",regex:"",next:"no_regex"}],regex:[{token:"regexp.keyword.operator",regex:"\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)"},{token:"string.regexp",regex:"/[sxngimy]*",next:"no_regex"},{token:"invalid",regex:/\{\d+\b,?\d*\}[+*]|[+*$^?][+*]|[$^][?]|\?{3,}/},{token:"constant.language.escape",regex:/\(\?[:=!]|\)|\{\d+\b,?\d*\}|[+*]\?|[()$^+*?.]/},{token:"constant.language.delimiter",regex:/\|/},{token:"constant.language.escape",regex:/\[\^?/,next:"regex_character_class"},{token:"empty",regex:"$",next:"no_regex"},{defaultToken:"string.regexp"}],regex_character_class:[{token:"regexp.charclass.keyword.operator",regex:"\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)"},{token:"constant.language.escape",regex:"]",next:"regex"},{token:"constant.language.escape",regex:"-"},{token:"empty",regex:"$",next:"no_regex"},{defaultToken:"string.regexp.charachterclass"}],default_parameter:[{token:"string",regex:"'(?=.)",push:[{token:"string",regex:"'|$",next:"pop"},{include:"qstring"}]},{token:"string",regex:'"(?=.)',push:[{token:"string",regex:'"|$',next:"pop"},{include:"qqstring"}]},{token:"constant.language",regex:"null|Infinity|NaN|undefined"},{token:"constant.numeric",regex:/0(?:[xX][0-9a-fA-F]+|[oO][0-7]+|[bB][01]+)\b/},{token:"constant.numeric",regex:/(?:\d\d*(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+\b)?/},{token:"punctuation.operator",regex:",",next:"function_arguments"},{token:"text",regex:"\\s+"},{token:"punctuation.operator",regex:"$"},{token:"empty",regex:"",next:"no_regex"}],function_arguments:[a("function_arguments"),{token:"variable.parameter",regex:l},{token:"punctuation.operator",regex:","},{token:"text",regex:"\\s+"},{token:"punctuation.operator",regex:"$"},{token:"empty",regex:"",next:"no_regex"}],qqstring:[{token:"constant.language.escape",regex:c},{token:"string",regex:"\\\\$",consumeLineEnd:!0},{token:"string",regex:'"|$',next:"no_regex"},{defaultToken:"string"}],qstring:[{token:"constant.language.escape",regex:c},{token:"string",regex:"\\\\$",consumeLineEnd:!0},{token:"string",regex:"'|$",next:"no_regex"},{defaultToken:"string"}]},(!i||!i.noES6)&&(this.$rules.no_regex.unshift({regex:"[{}]",onMatch:function(p,$,v){if(this.next=p=="{"?this.nextState:"",p=="{"&&v.length)v.unshift("start",$);else if(p=="}"&&v.length&&(v.shift(),this.next=v.shift(),this.next.indexOf("string")!=-1||this.next.indexOf("jsx")!=-1))return"paren.quasi.end";return p=="{"?"paren.lparen":"paren.rparen"},nextState:"start"},{token:"string.quasi.start",regex:/`/,push:[{token:"constant.language.escape",regex:c},{token:"paren.quasi.start",regex:/\${/,push:"start"},{token:"string.quasi.end",regex:/`/,next:"pop"},{defaultToken:"string.quasi"}]},{token:["variable.parameter","text"],regex:"("+l+")(\\s*)(?=\\=>)"},{token:"paren.lparen",regex:"(\\()(?=.+\\s*=>)",next:"function_arguments"},{token:"variable.language",regex:"(?:(?:(?:Weak)?(?:Set|Map))|Promise)\\b"}),this.$rules.function_arguments.unshift({token:"keyword.operator",regex:"=",next:"default_parameter"},{token:"keyword.operator",regex:"\\.{3}"}),this.$rules.property.unshift({token:"support.function",regex:"(findIndex|repeat|startsWith|endsWith|includes|isSafeInteger|trunc|cbrt|log2|log10|sign|then|catch|finally|resolve|reject|race|any|all|allSettled|keys|entries|isInteger)\\b(?=\\()"},{token:"constant.language",regex:"(?:MAX_SAFE_INTEGER|MIN_SAFE_INTEGER|EPSILON)\\b"}),(!i||i.jsx!=0)&&g.call(this)),this.embedRules(r,"doc-",[r.getEndRule("no_regex")]),this.normalizeRules()};u.inherits(n,f),h.JavaScriptHighlightRules=n}),ace.define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(e,h,m){var g=e("../range").Range,a=function(){};(function(){this.checkOutdent=function(u,r){return/^\s+$/.test(u)?/^\s*\}/.test(r):!1},this.autoOutdent=function(u,r){var f=u.getLine(r),l=f.match(/^(\s*\})/);if(!l)return 0;var n=l[1].length,i=u.findMatchingBracket({row:r,column:n});if(!i||i.row==r)return 0;var o=this.$getIndent(u.getLine(i.row));u.replace(new g(r,0,r,n-1),o)},this.$getIndent=function(u){return u.match(/^\s*/)[0]}}).call(a.prototype),h.MatchingBraceOutdent=a}),ace.define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(e,h,m){var g=e("../../lib/oop"),a=e("../../range").Range,u=e("./fold_mode").FoldMode,r=h.FoldMode=function(f){f&&(this.foldingStartMarker=new RegExp(this.foldingStartMarker.source.replace(/\|[^|]*?$/,"|"+f.start)),this.foldingStopMarker=new RegExp(this.foldingStopMarker.source.replace(/\|[^|]*?$/,"|"+f.end)))};g.inherits(r,u),function(){this.foldingStartMarker=/([\{\[\(])[^\}\]\)]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{\(]*([\}\]\)])|^[\s\*]*(\*\/)/,this.singleLineBlockCommentRe=/^\s*(\/\*).*\*\/\s*$/,this.tripleStarBlockCommentRe=/^\s*(\/\*\*\*).*\*\/\s*$/,this.startRegionRe=/^\s*(\/\*|\/\/)#?region\b/,this._getFoldWidgetBase=this.getFoldWidget,this.getFoldWidget=function(f,l,n){var i=f.getLine(n);if(this.singleLineBlockCommentRe.test(i)&&!this.startRegionRe.test(i)&&!this.tripleStarBlockCommentRe.test(i))return"";var o=this._getFoldWidgetBase(f,l,n);return!o&&this.startRegionRe.test(i)?"start":o},this.getFoldWidgetRange=function(f,l,n,i){var o=f.getLine(n);if(this.startRegionRe.test(o))return this.getCommentRegionBlock(f,o,n);var s=o.match(this.foldingStartMarker);if(s){var c=s.index;if(s[1])return this.openingBracketBlock(f,s[1],n,c);var p=f.getCommentFoldRange(n,c+s[0].length,1);return p&&!p.isMultiLine()&&(i?p=this.getSectionRange(f,n):l!="all"&&(p=null)),p}if(l!=="markbegin"){var s=o.match(this.foldingStopMarker);if(s){var c=s.index+s[0].length;return s[1]?this.closingBracketBlock(f,s[1],n,c):f.getCommentFoldRange(n,c,-1)}}},this.getSectionRange=function(f,l){var n=f.getLine(l),i=n.search(/\S/),o=l,s=n.length;l+=1;for(var c=l,p=f.getLength();++l$)break;var v=this.getFoldWidgetRange(f,"all",l);if(v){if(v.start.row<=o)break;if(v.isMultiLine())l=v.end.row;else if(i==$)break}c=l}}return new a(o,s,c,f.getLine(c).length)},this.getCommentRegionBlock=function(f,l,n){for(var i=l.search(/\s*$/),o=f.getLength(),s=n,c=/^\s*(?:\/\*|\/\/|--)#?(end)?region\b/,p=1;++ns)return new a(s,i,v,l.length)}}.call(r.prototype)}),ace.define("ace/mode/javascript",["require","exports","module","ace/lib/oop","ace/mode/text","ace/mode/javascript_highlight_rules","ace/mode/matching_brace_outdent","ace/worker/worker_client","ace/mode/behaviour/cstyle","ace/mode/folding/cstyle"],function(e,h,m){var g=e("../lib/oop"),a=e("./text").Mode,u=e("./javascript_highlight_rules").JavaScriptHighlightRules,r=e("./matching_brace_outdent").MatchingBraceOutdent,f=e("../worker/worker_client").WorkerClient,l=e("./behaviour/cstyle").CstyleBehaviour,n=e("./folding/cstyle").FoldMode,i=function(){this.HighlightRules=u,this.$outdent=new r,this.$behaviour=new l,this.foldingRules=new n};g.inherits(i,a),function(){this.lineCommentStart="//",this.blockComment={start:"/*",end:"*/"},this.$quotes={'"':'"',"'":"'","`":"`"},this.$pairQuotesAfter={"`":/\w/},this.getNextLineIndent=function(o,s,c){var p=this.$getIndent(s),$=this.getTokenizer().getLineTokens(s,o),v=$.tokens,C=$.state;if(v.length&&v[v.length-1].type=="comment")return p;if(o=="start"||o=="no_regex"){var y=s.match(/^.*(?:\bcase\b.*:|[\{\(\[])\s*$/);y&&(p+=c)}else if(o=="doc-start"){if(C=="start"||C=="no_regex")return"";var y=s.match(/^\s*(\/?)\*/);y&&(y[1]&&(p+=" "),p+="* ")}return p},this.checkOutdent=function(o,s,c){return this.$outdent.checkOutdent(s,c)},this.autoOutdent=function(o,s,c){this.$outdent.autoOutdent(s,c)},this.createWorker=function(o){var s=new f(["ace"],"ace/mode/javascript_worker","JavaScriptWorker");return s.attachToDocument(o.getDocument()),s.on("annotate",function(c){o.setAnnotations(c.data)}),s.on("terminate",function(){o.clearAnnotations()}),s},this.$id="ace/mode/javascript",this.snippetFileId="ace/snippets/javascript"}.call(i.prototype),h.Mode=i}),function(){ace.require(["ace/mode/javascript"],function(e){t&&(t.exports=e)})}()})(modeJavascript);var modeJson={exports:{}};(function(t,d){ace.define("ace/mode/json_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(e,h,m){var g=e("../lib/oop"),a=e("./text_highlight_rules").TextHighlightRules,u=function(){this.$rules={start:[{token:"variable",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]\\s*(?=:)'},{token:"string",regex:'"',next:"string"},{token:"constant.numeric",regex:"0[xX][0-9a-fA-F]+\\b"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:"constant.language.boolean",regex:"(?:true|false)\\b"},{token:"text",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:"comment",regex:"\\/\\/.*$"},{token:"comment.start",regex:"\\/\\*",next:"comment"},{token:"paren.lparen",regex:"[[({]"},{token:"paren.rparen",regex:"[\\])}]"},{token:"punctuation.operator",regex:/[,]/},{token:"text",regex:"\\s+"}],string:[{token:"constant.language.escape",regex:/\\(?:x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|["\\\/bfnrt])/},{token:"string",regex:'"|$',next:"start"},{defaultToken:"string"}],comment:[{token:"comment.end",regex:"\\*\\/",next:"start"},{defaultToken:"comment"}]}};g.inherits(u,a),h.JsonHighlightRules=u}),ace.define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(e,h,m){var g=e("../range").Range,a=function(){};(function(){this.checkOutdent=function(u,r){return/^\s+$/.test(u)?/^\s*\}/.test(r):!1},this.autoOutdent=function(u,r){var f=u.getLine(r),l=f.match(/^(\s*\})/);if(!l)return 0;var n=l[1].length,i=u.findMatchingBracket({row:r,column:n});if(!i||i.row==r)return 0;var o=this.$getIndent(u.getLine(i.row));u.replace(new g(r,0,r,n-1),o)},this.$getIndent=function(u){return u.match(/^\s*/)[0]}}).call(a.prototype),h.MatchingBraceOutdent=a}),ace.define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(e,h,m){var g=e("../../lib/oop"),a=e("../../range").Range,u=e("./fold_mode").FoldMode,r=h.FoldMode=function(f){f&&(this.foldingStartMarker=new RegExp(this.foldingStartMarker.source.replace(/\|[^|]*?$/,"|"+f.start)),this.foldingStopMarker=new RegExp(this.foldingStopMarker.source.replace(/\|[^|]*?$/,"|"+f.end)))};g.inherits(r,u),function(){this.foldingStartMarker=/([\{\[\(])[^\}\]\)]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{\(]*([\}\]\)])|^[\s\*]*(\*\/)/,this.singleLineBlockCommentRe=/^\s*(\/\*).*\*\/\s*$/,this.tripleStarBlockCommentRe=/^\s*(\/\*\*\*).*\*\/\s*$/,this.startRegionRe=/^\s*(\/\*|\/\/)#?region\b/,this._getFoldWidgetBase=this.getFoldWidget,this.getFoldWidget=function(f,l,n){var i=f.getLine(n);if(this.singleLineBlockCommentRe.test(i)&&!this.startRegionRe.test(i)&&!this.tripleStarBlockCommentRe.test(i))return"";var o=this._getFoldWidgetBase(f,l,n);return!o&&this.startRegionRe.test(i)?"start":o},this.getFoldWidgetRange=function(f,l,n,i){var o=f.getLine(n);if(this.startRegionRe.test(o))return this.getCommentRegionBlock(f,o,n);var s=o.match(this.foldingStartMarker);if(s){var c=s.index;if(s[1])return this.openingBracketBlock(f,s[1],n,c);var p=f.getCommentFoldRange(n,c+s[0].length,1);return p&&!p.isMultiLine()&&(i?p=this.getSectionRange(f,n):l!="all"&&(p=null)),p}if(l!=="markbegin"){var s=o.match(this.foldingStopMarker);if(s){var c=s.index+s[0].length;return s[1]?this.closingBracketBlock(f,s[1],n,c):f.getCommentFoldRange(n,c,-1)}}},this.getSectionRange=function(f,l){var n=f.getLine(l),i=n.search(/\S/),o=l,s=n.length;l+=1;for(var c=l,p=f.getLength();++l$)break;var v=this.getFoldWidgetRange(f,"all",l);if(v){if(v.start.row<=o)break;if(v.isMultiLine())l=v.end.row;else if(i==$)break}c=l}}return new a(o,s,c,f.getLine(c).length)},this.getCommentRegionBlock=function(f,l,n){for(var i=l.search(/\s*$/),o=f.getLength(),s=n,c=/^\s*(?:\/\*|\/\/|--)#?(end)?region\b/,p=1;++ns)return new a(s,i,v,l.length)}}.call(r.prototype)}),ace.define("ace/mode/json",["require","exports","module","ace/lib/oop","ace/mode/text","ace/mode/json_highlight_rules","ace/mode/matching_brace_outdent","ace/mode/folding/cstyle","ace/worker/worker_client"],function(e,h,m){var g=e("../lib/oop"),a=e("./text").Mode,u=e("./json_highlight_rules").JsonHighlightRules,r=e("./matching_brace_outdent").MatchingBraceOutdent,f=e("./folding/cstyle").FoldMode,l=e("../worker/worker_client").WorkerClient,n=function(){this.HighlightRules=u,this.$outdent=new r,this.$behaviour=this.$defaultBehaviour,this.foldingRules=new f};g.inherits(n,a),function(){this.lineCommentStart="//",this.blockComment={start:"/*",end:"*/"},this.getNextLineIndent=function(i,o,s){var c=this.$getIndent(o);if(i=="start"){var p=o.match(/^.*[\{\(\[]\s*$/);p&&(c+=s)}return c},this.checkOutdent=function(i,o,s){return this.$outdent.checkOutdent(o,s)},this.autoOutdent=function(i,o,s){this.$outdent.autoOutdent(o,s)},this.createWorker=function(i){var o=new l(["ace"],"ace/mode/json_worker","JsonWorker");return o.attachToDocument(i.getDocument()),o.on("annotate",function(s){i.setAnnotations(s.data)}),o.on("terminate",function(){i.clearAnnotations()}),o},this.$id="ace/mode/json"}.call(n.prototype),h.Mode=n}),function(){ace.require(["ace/mode/json"],function(e){t&&(t.exports=e)})}()})(modeJson);var modeCss={exports:{}};(function(t,d){ace.define("ace/mode/css_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/text_highlight_rules"],function(e,h,m){var g=e("../lib/oop");e("../lib/lang");var a=e("./text_highlight_rules").TextHighlightRules,u=h.supportType="align-content|align-items|align-self|all|animation|animation-delay|animation-direction|animation-duration|animation-fill-mode|animation-iteration-count|animation-name|animation-play-state|animation-timing-function|backface-visibility|background|background-attachment|background-blend-mode|background-clip|background-color|background-image|background-origin|background-position|background-repeat|background-size|border|border-bottom|border-bottom-color|border-bottom-left-radius|border-bottom-right-radius|border-bottom-style|border-bottom-width|border-collapse|border-color|border-image|border-image-outset|border-image-repeat|border-image-slice|border-image-source|border-image-width|border-left|border-left-color|border-left-style|border-left-width|border-radius|border-right|border-right-color|border-right-style|border-right-width|border-spacing|border-style|border-top|border-top-color|border-top-left-radius|border-top-right-radius|border-top-style|border-top-width|border-width|bottom|box-shadow|box-sizing|caption-side|clear|clip|color|column-count|column-fill|column-gap|column-rule|column-rule-color|column-rule-style|column-rule-width|column-span|column-width|columns|content|counter-increment|counter-reset|cursor|direction|display|empty-cells|filter|flex|flex-basis|flex-direction|flex-flow|flex-grow|flex-shrink|flex-wrap|float|font|font-family|font-size|font-size-adjust|font-stretch|font-style|font-variant|font-weight|hanging-punctuation|height|justify-content|left|letter-spacing|line-height|list-style|list-style-image|list-style-position|list-style-type|margin|margin-bottom|margin-left|margin-right|margin-top|max-height|max-width|max-zoom|min-height|min-width|min-zoom|nav-down|nav-index|nav-left|nav-right|nav-up|opacity|order|outline|outline-color|outline-offset|outline-style|outline-width|overflow|overflow-x|overflow-y|padding|padding-bottom|padding-left|padding-right|padding-top|page-break-after|page-break-before|page-break-inside|perspective|perspective-origin|position|quotes|resize|right|tab-size|table-layout|text-align|text-align-last|text-decoration|text-decoration-color|text-decoration-line|text-decoration-style|text-indent|text-justify|text-overflow|text-shadow|text-transform|top|transform|transform-origin|transform-style|transition|transition-delay|transition-duration|transition-property|transition-timing-function|unicode-bidi|user-select|user-zoom|vertical-align|visibility|white-space|width|word-break|word-spacing|word-wrap|z-index",r=h.supportFunction="rgb|rgba|url|attr|counter|counters",f=h.supportConstant="absolute|after-edge|after|all-scroll|all|alphabetic|always|antialiased|armenian|auto|avoid-column|avoid-page|avoid|balance|baseline|before-edge|before|below|bidi-override|block-line-height|block|bold|bolder|border-box|both|bottom|box|break-all|break-word|capitalize|caps-height|caption|center|central|char|circle|cjk-ideographic|clone|close-quote|col-resize|collapse|column|consider-shifts|contain|content-box|cover|crosshair|cubic-bezier|dashed|decimal-leading-zero|decimal|default|disabled|disc|disregard-shifts|distribute-all-lines|distribute-letter|distribute-space|distribute|dotted|double|e-resize|ease-in|ease-in-out|ease-out|ease|ellipsis|end|exclude-ruby|flex-end|flex-start|fill|fixed|georgian|glyphs|grid-height|groove|hand|hanging|hebrew|help|hidden|hiragana-iroha|hiragana|horizontal|icon|ideograph-alpha|ideograph-numeric|ideograph-parenthesis|ideograph-space|ideographic|inactive|include-ruby|inherit|initial|inline-block|inline-box|inline-line-height|inline-table|inline|inset|inside|inter-ideograph|inter-word|invert|italic|justify|katakana-iroha|katakana|keep-all|last|left|lighter|line-edge|line-through|line|linear|list-item|local|loose|lower-alpha|lower-greek|lower-latin|lower-roman|lowercase|lr-tb|ltr|mathematical|max-height|max-size|medium|menu|message-box|middle|move|n-resize|ne-resize|newspaper|no-change|no-close-quote|no-drop|no-open-quote|no-repeat|none|normal|not-allowed|nowrap|nw-resize|oblique|open-quote|outset|outside|overline|padding-box|page|pointer|pre-line|pre-wrap|pre|preserve-3d|progress|relative|repeat-x|repeat-y|repeat|replaced|reset-size|ridge|right|round|row-resize|rtl|s-resize|scroll|se-resize|separate|slice|small-caps|small-caption|solid|space|square|start|static|status-bar|step-end|step-start|steps|stretch|strict|sub|super|sw-resize|table-caption|table-cell|table-column-group|table-column|table-footer-group|table-header-group|table-row-group|table-row|table|tb-rl|text-after-edge|text-before-edge|text-bottom|text-size|text-top|text|thick|thin|transparent|underline|upper-alpha|upper-latin|upper-roman|uppercase|use-script|vertical-ideographic|vertical-text|visible|w-resize|wait|whitespace|z-index|zero|zoom",l=h.supportConstantColor="aliceblue|antiquewhite|aqua|aquamarine|azure|beige|bisque|black|blanchedalmond|blue|blueviolet|brown|burlywood|cadetblue|chartreuse|chocolate|coral|cornflowerblue|cornsilk|crimson|cyan|darkblue|darkcyan|darkgoldenrod|darkgray|darkgreen|darkgrey|darkkhaki|darkmagenta|darkolivegreen|darkorange|darkorchid|darkred|darksalmon|darkseagreen|darkslateblue|darkslategray|darkslategrey|darkturquoise|darkviolet|deeppink|deepskyblue|dimgray|dimgrey|dodgerblue|firebrick|floralwhite|forestgreen|fuchsia|gainsboro|ghostwhite|gold|goldenrod|gray|green|greenyellow|grey|honeydew|hotpink|indianred|indigo|ivory|khaki|lavender|lavenderblush|lawngreen|lemonchiffon|lightblue|lightcoral|lightcyan|lightgoldenrodyellow|lightgray|lightgreen|lightgrey|lightpink|lightsalmon|lightseagreen|lightskyblue|lightslategray|lightslategrey|lightsteelblue|lightyellow|lime|limegreen|linen|magenta|maroon|mediumaquamarine|mediumblue|mediumorchid|mediumpurple|mediumseagreen|mediumslateblue|mediumspringgreen|mediumturquoise|mediumvioletred|midnightblue|mintcream|mistyrose|moccasin|navajowhite|navy|oldlace|olive|olivedrab|orange|orangered|orchid|palegoldenrod|palegreen|paleturquoise|palevioletred|papayawhip|peachpuff|peru|pink|plum|powderblue|purple|rebeccapurple|red|rosybrown|royalblue|saddlebrown|salmon|sandybrown|seagreen|seashell|sienna|silver|skyblue|slateblue|slategray|slategrey|snow|springgreen|steelblue|tan|teal|thistle|tomato|turquoise|violet|wheat|white|whitesmoke|yellow|yellowgreen",n=h.supportConstantFonts="arial|century|comic|courier|cursive|fantasy|garamond|georgia|helvetica|impact|lucida|symbol|system|tahoma|times|trebuchet|utopia|verdana|webdings|sans-serif|serif|monospace",i=h.numRe="\\-?(?:(?:[0-9]+(?:\\.[0-9]+)?)|(?:\\.[0-9]+))",o=h.pseudoElements="(\\:+)\\b(after|before|first-letter|first-line|moz-selection|selection)\\b",s=h.pseudoClasses="(:)\\b(active|checked|disabled|empty|enabled|first-child|first-of-type|focus|hover|indeterminate|invalid|last-child|last-of-type|link|not|nth-child|nth-last-child|nth-last-of-type|nth-of-type|only-child|only-of-type|required|root|target|valid|visited)\\b",c=function(){var p=this.createKeywordMapper({"support.function":r,"support.constant":f,"support.type":u,"support.constant.color":l,"support.constant.fonts":n},"text",!0);this.$rules={start:[{include:["strings","url","comments"]},{token:"paren.lparen",regex:"\\{",next:"ruleset"},{token:"paren.rparen",regex:"\\}"},{token:"string",regex:"@(?!viewport)",next:"media"},{token:"keyword",regex:"#[a-z0-9-_]+"},{token:"keyword",regex:"%"},{token:"variable",regex:"\\.[a-z0-9-_]+"},{token:"string",regex:":[a-z0-9-_]+"},{token:"constant.numeric",regex:i},{token:"constant",regex:"[a-z0-9-_]+"},{caseInsensitive:!0}],media:[{include:["strings","url","comments"]},{token:"paren.lparen",regex:"\\{",next:"start"},{token:"paren.rparen",regex:"\\}",next:"start"},{token:"string",regex:";",next:"start"},{token:"keyword",regex:"(?:media|supports|document|charset|import|namespace|media|supports|document|page|font|keyframes|viewport|counter-style|font-feature-values|swash|ornaments|annotation|stylistic|styleset|character-variant)"}],comments:[{token:"comment",regex:"\\/\\*",push:[{token:"comment",regex:"\\*\\/",next:"pop"},{defaultToken:"comment"}]}],ruleset:[{regex:"-(webkit|ms|moz|o)-",token:"text"},{token:"punctuation.operator",regex:"[:;]"},{token:"paren.rparen",regex:"\\}",next:"start"},{include:["strings","url","comments"]},{token:["constant.numeric","keyword"],regex:"("+i+")(ch|cm|deg|em|ex|fr|gd|grad|Hz|in|kHz|mm|ms|pc|pt|px|rad|rem|s|turn|vh|vmax|vmin|vm|vw|%)"},{token:"constant.numeric",regex:i},{token:"constant.numeric",regex:"#[a-f0-9]{6}"},{token:"constant.numeric",regex:"#[a-f0-9]{3}"},{token:["punctuation","entity.other.attribute-name.pseudo-element.css"],regex:o},{token:["punctuation","entity.other.attribute-name.pseudo-class.css"],regex:s},{include:"url"},{token:p,regex:"\\-?[a-zA-Z_][a-zA-Z0-9_\\-]*"},{caseInsensitive:!0}],url:[{token:"support.function",regex:"(?:url(:?-prefix)?|domain|regexp)\\(",push:[{token:"support.function",regex:"\\)",next:"pop"},{defaultToken:"string"}]}],strings:[{token:"string.start",regex:"'",push:[{token:"string.end",regex:"'|$",next:"pop"},{include:"escapes"},{token:"constant.language.escape",regex:/\\$/,consumeLineEnd:!0},{defaultToken:"string"}]},{token:"string.start",regex:'"',push:[{token:"string.end",regex:'"|$',next:"pop"},{include:"escapes"},{token:"constant.language.escape",regex:/\\$/,consumeLineEnd:!0},{defaultToken:"string"}]}],escapes:[{token:"constant.language.escape",regex:/\\([a-fA-F\d]{1,6}|[^a-fA-F\d])/}]},this.normalizeRules()};g.inherits(c,a),h.CssHighlightRules=c}),ace.define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(e,h,m){var g=e("../range").Range,a=function(){};(function(){this.checkOutdent=function(u,r){return/^\s+$/.test(u)?/^\s*\}/.test(r):!1},this.autoOutdent=function(u,r){var f=u.getLine(r),l=f.match(/^(\s*\})/);if(!l)return 0;var n=l[1].length,i=u.findMatchingBracket({row:r,column:n});if(!i||i.row==r)return 0;var o=this.$getIndent(u.getLine(i.row));u.replace(new g(r,0,r,n-1),o)},this.$getIndent=function(u){return u.match(/^\s*/)[0]}}).call(a.prototype),h.MatchingBraceOutdent=a}),ace.define("ace/mode/css_completions",["require","exports","module"],function(e,h,m){var g={background:{"#$0":1},"background-color":{"#$0":1,transparent:1,fixed:1},"background-image":{"url('/$0')":1},"background-repeat":{repeat:1,"repeat-x":1,"repeat-y":1,"no-repeat":1,inherit:1},"background-position":{bottom:2,center:2,left:2,right:2,top:2,inherit:2},"background-attachment":{scroll:1,fixed:1},"background-size":{cover:1,contain:1},"background-clip":{"border-box":1,"padding-box":1,"content-box":1},"background-origin":{"border-box":1,"padding-box":1,"content-box":1},border:{"solid $0":1,"dashed $0":1,"dotted $0":1,"#$0":1},"border-color":{"#$0":1},"border-style":{solid:2,dashed:2,dotted:2,double:2,groove:2,hidden:2,inherit:2,inset:2,none:2,outset:2,ridged:2},"border-collapse":{collapse:1,separate:1},bottom:{px:1,em:1,"%":1},clear:{left:1,right:1,both:1,none:1},color:{"#$0":1,"rgb(#$00,0,0)":1},cursor:{default:1,pointer:1,move:1,text:1,wait:1,help:1,progress:1,"n-resize":1,"ne-resize":1,"e-resize":1,"se-resize":1,"s-resize":1,"sw-resize":1,"w-resize":1,"nw-resize":1},display:{none:1,block:1,inline:1,"inline-block":1,"table-cell":1},"empty-cells":{show:1,hide:1},float:{left:1,right:1,none:1},"font-family":{Arial:2,"Comic Sans MS":2,Consolas:2,"Courier New":2,Courier:2,Georgia:2,Monospace:2,"Sans-Serif":2,"Segoe UI":2,Tahoma:2,"Times New Roman":2,"Trebuchet MS":2,Verdana:1},"font-size":{px:1,em:1,"%":1},"font-weight":{bold:1,normal:1},"font-style":{italic:1,normal:1},"font-variant":{normal:1,"small-caps":1},height:{px:1,em:1,"%":1},left:{px:1,em:1,"%":1},"letter-spacing":{normal:1},"line-height":{normal:1},"list-style-type":{none:1,disc:1,circle:1,square:1,decimal:1,"decimal-leading-zero":1,"lower-roman":1,"upper-roman":1,"lower-greek":1,"lower-latin":1,"upper-latin":1,georgian:1,"lower-alpha":1,"upper-alpha":1},margin:{px:1,em:1,"%":1},"margin-right":{px:1,em:1,"%":1},"margin-left":{px:1,em:1,"%":1},"margin-top":{px:1,em:1,"%":1},"margin-bottom":{px:1,em:1,"%":1},"max-height":{px:1,em:1,"%":1},"max-width":{px:1,em:1,"%":1},"min-height":{px:1,em:1,"%":1},"min-width":{px:1,em:1,"%":1},overflow:{hidden:1,visible:1,auto:1,scroll:1},"overflow-x":{hidden:1,visible:1,auto:1,scroll:1},"overflow-y":{hidden:1,visible:1,auto:1,scroll:1},padding:{px:1,em:1,"%":1},"padding-top":{px:1,em:1,"%":1},"padding-right":{px:1,em:1,"%":1},"padding-bottom":{px:1,em:1,"%":1},"padding-left":{px:1,em:1,"%":1},"page-break-after":{auto:1,always:1,avoid:1,left:1,right:1},"page-break-before":{auto:1,always:1,avoid:1,left:1,right:1},position:{absolute:1,relative:1,fixed:1,static:1},right:{px:1,em:1,"%":1},"table-layout":{fixed:1,auto:1},"text-decoration":{none:1,underline:1,"line-through":1,blink:1},"text-align":{left:1,right:1,center:1,justify:1},"text-transform":{capitalize:1,uppercase:1,lowercase:1,none:1},top:{px:1,em:1,"%":1},"vertical-align":{top:1,bottom:1},visibility:{hidden:1,visible:1},"white-space":{nowrap:1,normal:1,pre:1,"pre-line":1,"pre-wrap":1},width:{px:1,em:1,"%":1},"word-spacing":{normal:1},filter:{"alpha(opacity=$0100)":1},"text-shadow":{"$02px 2px 2px #777":1},"text-overflow":{"ellipsis-word":1,clip:1,ellipsis:1},"-moz-border-radius":1,"-moz-border-radius-topright":1,"-moz-border-radius-bottomright":1,"-moz-border-radius-topleft":1,"-moz-border-radius-bottomleft":1,"-webkit-border-radius":1,"-webkit-border-top-right-radius":1,"-webkit-border-top-left-radius":1,"-webkit-border-bottom-right-radius":1,"-webkit-border-bottom-left-radius":1,"-moz-box-shadow":1,"-webkit-box-shadow":1,transform:{"rotate($00deg)":1,"skew($00deg)":1},"-moz-transform":{"rotate($00deg)":1,"skew($00deg)":1},"-webkit-transform":{"rotate($00deg)":1,"skew($00deg)":1}},a=function(){};(function(){this.completionsDefined=!1,this.defineCompletions=function(){if(document){var u=document.createElement("c").style;for(var r in u)if(typeof u[r]=="string"){var f=r.replace(/[A-Z]/g,function(l){return"-"+l.toLowerCase()});g.hasOwnProperty(f)||(g[f]=1)}}this.completionsDefined=!0},this.getCompletions=function(u,r,f,l){if(this.completionsDefined||this.defineCompletions(),u==="ruleset"||r.$mode.$id=="ace/mode/scss"){var n=r.getLine(f.row).substr(0,f.column),i=/\([^)]*$/.test(n);return i&&(n=n.substr(n.lastIndexOf("(")+1)),/:[^;]+$/.test(n)?(/([\w\-]+):[^:]*$/.test(n),this.getPropertyValueCompletions(u,r,f,l)):this.getPropertyCompletions(u,r,f,l,i)}return[]},this.getPropertyCompletions=function(u,r,f,l,n){n=n||!1;var i=Object.keys(g);return i.map(function(o){return{caption:o,snippet:o+": $0"+(n?"":";"),meta:"property",score:1e6}})},this.getPropertyValueCompletions=function(u,r,f,l){var n=r.getLine(f.row).substr(0,f.column),i=(/([\w\-]+):[^:]*$/.exec(n)||{})[1];if(!i)return[];var o=[];return i in g&&typeof g[i]=="object"&&(o=Object.keys(g[i])),o.map(function(s){return{caption:s,snippet:s,meta:"property value",score:1e6}})}}).call(a.prototype),h.CssCompletions=a}),ace.define("ace/mode/behaviour/css",["require","exports","module","ace/lib/oop","ace/mode/behaviour","ace/mode/behaviour/cstyle","ace/token_iterator"],function(e,h,m){var g=e("../../lib/oop");e("../behaviour").Behaviour;var a=e("./cstyle").CstyleBehaviour,u=e("../../token_iterator").TokenIterator,r=function(){this.inherit(a),this.add("colon","insertion",function(f,l,n,i,o){if(o===":"&&n.selection.isEmpty()){var s=n.getCursorPosition(),c=new u(i,s.row,s.column),p=c.getCurrentToken();if(p&&p.value.match(/\s+/)&&(p=c.stepBackward()),p&&p.type==="support.type"){var $=i.doc.getLine(s.row),v=$.substring(s.column,s.column+1);if(v===":")return{text:"",selection:[1,1]};if(/^(\s+[^;]|\s*$)/.test($.substring(s.column)))return{text:":;",selection:[1,1]}}}}),this.add("colon","deletion",function(f,l,n,i,o){var s=i.doc.getTextRange(o);if(!o.isMultiLine()&&s===":"){var c=n.getCursorPosition(),p=new u(i,c.row,c.column),$=p.getCurrentToken();if($&&$.value.match(/\s+/)&&($=p.stepBackward()),$&&$.type==="support.type"){var v=i.doc.getLine(o.start.row),C=v.substring(o.end.column,o.end.column+1);if(C===";")return o.end.column++,o}}}),this.add("semicolon","insertion",function(f,l,n,i,o){if(o===";"&&n.selection.isEmpty()){var s=n.getCursorPosition(),c=i.doc.getLine(s.row),p=c.substring(s.column,s.column+1);if(p===";")return{text:"",selection:[1,1]}}}),this.add("!important","insertion",function(f,l,n,i,o){if(o==="!"&&n.selection.isEmpty()){var s=n.getCursorPosition(),c=i.doc.getLine(s.row);if(/^\s*(;|}|$)/.test(c.substring(s.column)))return{text:"!important",selection:[10,10]}}})};g.inherits(r,a),h.CssBehaviour=r}),ace.define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(e,h,m){var g=e("../../lib/oop"),a=e("../../range").Range,u=e("./fold_mode").FoldMode,r=h.FoldMode=function(f){f&&(this.foldingStartMarker=new RegExp(this.foldingStartMarker.source.replace(/\|[^|]*?$/,"|"+f.start)),this.foldingStopMarker=new RegExp(this.foldingStopMarker.source.replace(/\|[^|]*?$/,"|"+f.end)))};g.inherits(r,u),function(){this.foldingStartMarker=/([\{\[\(])[^\}\]\)]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{\(]*([\}\]\)])|^[\s\*]*(\*\/)/,this.singleLineBlockCommentRe=/^\s*(\/\*).*\*\/\s*$/,this.tripleStarBlockCommentRe=/^\s*(\/\*\*\*).*\*\/\s*$/,this.startRegionRe=/^\s*(\/\*|\/\/)#?region\b/,this._getFoldWidgetBase=this.getFoldWidget,this.getFoldWidget=function(f,l,n){var i=f.getLine(n);if(this.singleLineBlockCommentRe.test(i)&&!this.startRegionRe.test(i)&&!this.tripleStarBlockCommentRe.test(i))return"";var o=this._getFoldWidgetBase(f,l,n);return!o&&this.startRegionRe.test(i)?"start":o},this.getFoldWidgetRange=function(f,l,n,i){var o=f.getLine(n);if(this.startRegionRe.test(o))return this.getCommentRegionBlock(f,o,n);var s=o.match(this.foldingStartMarker);if(s){var c=s.index;if(s[1])return this.openingBracketBlock(f,s[1],n,c);var p=f.getCommentFoldRange(n,c+s[0].length,1);return p&&!p.isMultiLine()&&(i?p=this.getSectionRange(f,n):l!="all"&&(p=null)),p}if(l!=="markbegin"){var s=o.match(this.foldingStopMarker);if(s){var c=s.index+s[0].length;return s[1]?this.closingBracketBlock(f,s[1],n,c):f.getCommentFoldRange(n,c,-1)}}},this.getSectionRange=function(f,l){var n=f.getLine(l),i=n.search(/\S/),o=l,s=n.length;l+=1;for(var c=l,p=f.getLength();++l$)break;var v=this.getFoldWidgetRange(f,"all",l);if(v){if(v.start.row<=o)break;if(v.isMultiLine())l=v.end.row;else if(i==$)break}c=l}}return new a(o,s,c,f.getLine(c).length)},this.getCommentRegionBlock=function(f,l,n){for(var i=l.search(/\s*$/),o=f.getLength(),s=n,c=/^\s*(?:\/\*|\/\/|--)#?(end)?region\b/,p=1;++ns)return new a(s,i,v,l.length)}}.call(r.prototype)}),ace.define("ace/mode/css",["require","exports","module","ace/lib/oop","ace/mode/text","ace/mode/css_highlight_rules","ace/mode/matching_brace_outdent","ace/worker/worker_client","ace/mode/css_completions","ace/mode/behaviour/css","ace/mode/folding/cstyle"],function(e,h,m){var g=e("../lib/oop"),a=e("./text").Mode,u=e("./css_highlight_rules").CssHighlightRules,r=e("./matching_brace_outdent").MatchingBraceOutdent,f=e("../worker/worker_client").WorkerClient,l=e("./css_completions").CssCompletions,n=e("./behaviour/css").CssBehaviour,i=e("./folding/cstyle").FoldMode,o=function(){this.HighlightRules=u,this.$outdent=new r,this.$behaviour=new n,this.$completer=new l,this.foldingRules=new i};g.inherits(o,a),function(){this.foldingRules="cStyle",this.blockComment={start:"/*",end:"*/"},this.getNextLineIndent=function(s,c,p){var $=this.$getIndent(c),v=this.getTokenizer().getLineTokens(c,s).tokens;if(v.length&&v[v.length-1].type=="comment")return $;var C=c.match(/^.*\{\s*$/);return C&&($+=p),$},this.checkOutdent=function(s,c,p){return this.$outdent.checkOutdent(c,p)},this.autoOutdent=function(s,c,p){this.$outdent.autoOutdent(c,p)},this.getCompletions=function(s,c,p,$){return this.$completer.getCompletions(s,c,p,$)},this.createWorker=function(s){var c=new f(["ace"],"ace/mode/css_worker","Worker");return c.attachToDocument(s.getDocument()),c.on("annotate",function(p){s.setAnnotations(p.data)}),c.on("terminate",function(){s.clearAnnotations()}),c},this.$id="ace/mode/css",this.snippetFileId="ace/snippets/css"}.call(o.prototype),h.Mode=o}),function(){ace.require(["ace/mode/css"],function(e){t&&(t.exports=e)})}()})(modeCss);var extLanguage_tools={exports:{}};(function(t,d){ace.define("ace/snippets",["require","exports","module","ace/lib/dom","ace/lib/oop","ace/lib/event_emitter","ace/lib/lang","ace/range","ace/range_list","ace/keyboard/hash_handler","ace/tokenizer","ace/clipboard","ace/editor"],function(e,h,m){function g(b){var E=new Date().toLocaleString("en-us",b);return E.length==1?"0"+E:E}var a=e("./lib/dom"),u=e("./lib/oop"),r=e("./lib/event_emitter").EventEmitter,f=e("./lib/lang"),l=e("./range").Range,n=e("./range_list").RangeList,i=e("./keyboard/hash_handler").HashHandler,o=e("./tokenizer").Tokenizer,s=e("./clipboard"),c={CURRENT_WORD:function(b){return b.session.getTextRange(b.session.getWordRange())},SELECTION:function(b,E,x){var O=b.session.getTextRange();return x?O.replace(/\n\r?([ \t]*\S)/g,` +`+x+"$1"):O},CURRENT_LINE:function(b){return b.session.getLine(b.getCursorPosition().row)},PREV_LINE:function(b){return b.session.getLine(b.getCursorPosition().row-1)},LINE_INDEX:function(b){return b.getCursorPosition().row},LINE_NUMBER:function(b){return b.getCursorPosition().row+1},SOFT_TABS:function(b){return b.session.getUseSoftTabs()?"YES":"NO"},TAB_SIZE:function(b){return b.session.getTabSize()},CLIPBOARD:function(b){return s.getText&&s.getText()},FILENAME:function(b){return/[^/\\]*$/.exec(this.FILEPATH(b))[0]},FILENAME_BASE:function(b){return/[^/\\]*$/.exec(this.FILEPATH(b))[0].replace(/\.[^.]*$/,"")},DIRECTORY:function(b){return this.FILEPATH(b).replace(/[^/\\]*$/,"")},FILEPATH:function(b){return"/not implemented.txt"},WORKSPACE_NAME:function(){return"Unknown"},FULLNAME:function(){return"Unknown"},BLOCK_COMMENT_START:function(b){var E=b.session.$mode||{};return E.blockComment&&E.blockComment.start||""},BLOCK_COMMENT_END:function(b){var E=b.session.$mode||{};return E.blockComment&&E.blockComment.end||""},LINE_COMMENT:function(b){var E=b.session.$mode||{};return E.lineCommentStart||""},CURRENT_YEAR:g.bind(null,{year:"numeric"}),CURRENT_YEAR_SHORT:g.bind(null,{year:"2-digit"}),CURRENT_MONTH:g.bind(null,{month:"numeric"}),CURRENT_MONTH_NAME:g.bind(null,{month:"long"}),CURRENT_MONTH_NAME_SHORT:g.bind(null,{month:"short"}),CURRENT_DATE:g.bind(null,{day:"2-digit"}),CURRENT_DAY_NAME:g.bind(null,{weekday:"long"}),CURRENT_DAY_NAME_SHORT:g.bind(null,{weekday:"short"}),CURRENT_HOUR:g.bind(null,{hour:"2-digit",hour12:!1}),CURRENT_MINUTE:g.bind(null,{minute:"2-digit"}),CURRENT_SECOND:g.bind(null,{second:"2-digit"})};c.SELECTED_TEXT=c.SELECTION;var p=function(){function b(){this.snippetMap={},this.snippetNameMap={},this.variables=c}return b.prototype.getTokenizer=function(){return b.$tokenizer||this.createTokenizer()},b.prototype.createTokenizer=function(){function E(M){return M=M.substr(1),/^\d+$/.test(M)?[{tabstopId:parseInt(M,10)}]:[{text:M}]}function x(M){return"(?:[^\\\\"+M+"]|\\\\.)"}var O={regex:"/("+x("/")+"+)/",onMatch:function(M,k,T){var S=T[0];return S.fmtString=!0,S.guard=M.slice(1,-1),S.flag="",""},next:"formatString"};return b.$tokenizer=new o({start:[{regex:/\\./,onMatch:function(M,k,T){var S=M[1];return(S=="}"&&T.length||"`$\\".indexOf(S)!=-1)&&(M=S),[M]}},{regex:/}/,onMatch:function(M,k,T){return[T.length?T.shift():M]}},{regex:/\$(?:\d+|\w+)/,onMatch:E},{regex:/\$\{[\dA-Z_a-z]+/,onMatch:function(M,k,T){var S=E(M.substr(1));return T.unshift(S[0]),S},next:"snippetVar"},{regex:/\n/,token:"newline",merge:!1}],snippetVar:[{regex:"\\|"+x("\\|")+"*\\|",onMatch:function(M,k,T){var S=M.slice(1,-1).replace(/\\[,|\\]|,/g,function(w){return w.length==2?w[1]:"\0"}).split("\0").map(function(w){return{value:w}});return T[0].choices=S,[S[0]]},next:"start"},O,{regex:"([^:}\\\\]|\\\\.)*:?",token:"",next:"start"}],formatString:[{regex:/:/,onMatch:function(M,k,T){return T.length&&T[0].expectElse?(T[0].expectElse=!1,T[0].ifEnd={elseEnd:T[0]},[T[0].ifEnd]):":"}},{regex:/\\./,onMatch:function(M,k,T){var S=M[1];return S=="}"&&T.length||"`$\\".indexOf(S)!=-1?M=S:S=="n"?M=` +`:S=="t"?M=" ":"ulULE".indexOf(S)!=-1&&(M={changeCase:S,local:S>"a"}),[M]}},{regex:"/\\w*}",onMatch:function(M,k,T){var S=T.shift();return S&&(S.flag=M.slice(1,-1)),this.next=S&&S.tabstopId?"start":"",[S||M]},next:"start"},{regex:/\$(?:\d+|\w+)/,onMatch:function(M,k,T){return[{text:M.slice(1)}]}},{regex:/\${\w+/,onMatch:function(M,k,T){var S={text:M.slice(2)};return T.unshift(S),[S]},next:"formatStringVar"},{regex:/\n/,token:"newline",merge:!1},{regex:/}/,onMatch:function(M,k,T){var S=T.shift();return this.next=S&&S.tabstopId?"start":"",[S||M]},next:"start"}],formatStringVar:[{regex:/:\/\w+}/,onMatch:function(M,k,T){var S=T[0];return S.formatFunction=M.slice(2,-1),[T.shift()]},next:"formatString"},O,{regex:/:[\?\-+]?/,onMatch:function(M,k,T){M[1]=="+"&&(T[0].ifEnd=T[0]),M[1]=="?"&&(T[0].expectElse=!0)},next:"formatString"},{regex:"([^:}\\\\]|\\\\.)*:?",token:"",next:"formatString"}]}),b.$tokenizer},b.prototype.tokenizeTmSnippet=function(E,x){return this.getTokenizer().getLineTokens(E,x).tokens.map(function(O){return O.value||O})},b.prototype.getVariableValue=function(E,x,O){if(/^\d+$/.test(x))return(this.variables.__||{})[x]||"";if(/^[A-Z]\d+$/.test(x))return(this.variables[x[0]+"__"]||{})[x.substr(1)]||"";if(x=x.replace(/^TM_/,""),!this.variables.hasOwnProperty(x))return"";var M=this.variables[x];return typeof M=="function"&&(M=this.variables[x](E,x,O)),M==null?"":M},b.prototype.tmStrFormat=function(E,x,O){if(!x.fmt)return E;var M=x.flag||"",k=x.guard;k=new RegExp(k,M.replace(/[^gim]/g,""));var T=typeof x.fmt=="string"?this.tokenizeTmSnippet(x.fmt,"formatString"):x.fmt,S=this,w=E.replace(k,function(){var L=S.variables.__;S.variables.__=[].slice.call(arguments);for(var q=S.resolveVariables(T,O),A="E",I=0;I=0&&w.splice(L,1)}}var M=this.snippetMap,k=this.snippetNameMap;E.content?O(E):Array.isArray(E)&&E.forEach(O)},b.prototype.parseSnippetFile=function(E){E=E.replace(/\r/g,"");for(var x=[],O={},M=/^#.*|^({[\s\S]*})\s*$|^(\S+) (.*)$|^((?:\n*\t.*)+)/gm,k;k=M.exec(E);){if(k[1])try{O=JSON.parse(k[1]),x.push(O)}catch{}if(k[4])O.content=k[4].replace(/^\t/gm,""),x.push(O),O={};else{var T=k[2],S=k[3];if(T=="regex"){var w=/\/((?:[^\/\\]|\\.)*)|$/g;O.guard=w.exec(S)[1],O.trigger=w.exec(S)[1],O.endTrigger=w.exec(S)[1],O.endGuard=w.exec(S)[1]}else T=="snippet"?(O.tabTrigger=S.match(/^\S*/)[0],O.name||(O.name=S)):T&&(O[T]=S)}}return x},b.prototype.getSnippetByName=function(E,x){var O=this.snippetNameMap,M;return this.getActiveScopes(x).some(function(k){var T=O[k];return T&&(M=T[E]),!!M},this),M},b}();u.implement(p.prototype,r);var $=function(b,E,x){function O(D){for(var W=[],H=0;H1?(P=W[W.length-1].length,N+=W.length-1):P+=D.length,j+=D}else D&&(D.start?D.end={row:N,column:P}:D.start={row:N,column:P})}),{text:j,tabstops:L,tokens:w}},v=function(){function b(E){if(this.index=0,this.ranges=[],this.tabstops=[],E.tabstopManager)return E.tabstopManager;E.tabstopManager=this,this.$onChange=this.onChange.bind(this),this.$onChangeSelection=f.delayedCall(this.onChangeSelection.bind(this)).schedule,this.$onChangeSession=this.onChangeSession.bind(this),this.$onAfterExec=this.onAfterExec.bind(this),this.attach(E)}return b.prototype.attach=function(E){this.$openTabstops=null,this.selectedTabstop=null,this.editor=E,this.session=E.session,this.editor.on("change",this.$onChange),this.editor.on("changeSelection",this.$onChangeSelection),this.editor.on("changeSession",this.$onChangeSession),this.editor.commands.on("afterExec",this.$onAfterExec),this.editor.keyBinding.addKeyboardHandler(this.keyboardHandler)},b.prototype.detach=function(){this.tabstops.forEach(this.removeTabstopMarkers,this),this.ranges.length=0,this.tabstops.length=0,this.selectedTabstop=null,this.editor.off("change",this.$onChange),this.editor.off("changeSelection",this.$onChangeSelection),this.editor.off("changeSession",this.$onChangeSession),this.editor.commands.off("afterExec",this.$onAfterExec),this.editor.keyBinding.removeKeyboardHandler(this.keyboardHandler),this.editor.tabstopManager=null,this.session=null,this.editor=null},b.prototype.onChange=function(E){for(var x=E.action[0]=="r",O=this.selectedTabstop||{},M=O.parents||{},k=this.tabstops.slice(),T=0;T2&&(this.tabstops.length&&S.push(S.splice(2,1)[0]),this.tabstops.splice.apply(this.tabstops,S))},b.prototype.addTabstopMarkers=function(E){var x=this.session;E.forEach(function(O){O.markerId||(O.markerId=x.addMarker(O,"ace_snippet-marker","text"))})},b.prototype.removeTabstopMarkers=function(E){var x=this.session;E.forEach(function(O){x.removeMarker(O.markerId),O.markerId=null})},b.prototype.updateTabstopMarkers=function(){if(!!this.selectedTabstop){var E=this.selectedTabstop.snippetId;this.selectedTabstop.index===0&&E--,this.tabstops.forEach(function(x){x.snippetId===E?this.addTabstopMarkers(x):this.removeTabstopMarkers(x)},this)}},b.prototype.removeRange=function(E){var x=E.tabstop.indexOf(E);x!=-1&&E.tabstop.splice(x,1),x=this.ranges.indexOf(E),x!=-1&&this.ranges.splice(x,1),x=E.tabstop.rangeList.ranges.indexOf(E),x!=-1&&E.tabstop.splice(x,1),this.session.removeMarker(E.markerId),E.tabstop.length||(x=this.tabstops.indexOf(E.tabstop),x!=-1&&this.tabstops.splice(x,1),this.tabstops.length||this.detach())},b}();v.prototype.keyboardHandler=new i,v.prototype.keyboardHandler.bindKeys({Tab:function(b){h.snippetManager&&h.snippetManager.expandWithTab(b)||(b.tabstopManager.tabNext(1),b.renderer.scrollCursorIntoView())},"Shift-Tab":function(b){b.tabstopManager.tabNext(-1),b.renderer.scrollCursorIntoView()},Esc:function(b){b.tabstopManager.detach()}});var C=function(b,E){b.row==0&&(b.column+=E.column),b.row+=E.row},y=function(b,E){b.row==E.row&&(b.column-=E.column),b.row-=E.row};a.importCssString(` +.ace_snippet-marker { + -moz-box-sizing: border-box; + box-sizing: border-box; + background: rgba(194, 193, 208, 0.09); + border: 1px dotted rgba(211, 208, 235, 0.62); + position: absolute; +}`,"snippets.css",!1),h.snippetManager=new p;var _=e("./editor").Editor;(function(){this.insertSnippet=function(b,E){return h.snippetManager.insertSnippet(this,b,E)},this.expandSnippet=function(b){return h.snippetManager.expandWithTab(this,b)}}).call(_.prototype)}),ace.define("ace/autocomplete/popup",["require","exports","module","ace/virtual_renderer","ace/editor","ace/range","ace/lib/event","ace/lib/lang","ace/lib/dom","ace/config","ace/lib/useragent"],function(e,h,m){var g=e("../virtual_renderer").VirtualRenderer,a=e("../editor").Editor,u=e("../range").Range,r=e("../lib/event"),f=e("../lib/lang"),l=e("../lib/dom"),n=e("../config").nls,i=e("./../lib/useragent"),o=function(C){return"suggest-aria-id:".concat(C)},s=i.isSafari?"menu":"listbox",c=i.isSafari?"menuitem":"option",p=i.isSafari?"aria-current":"aria-selected",$=function(C){var y=new g(C);y.$maxLines=4;var _=new a(y);return _.setHighlightActiveLine(!1),_.setShowPrintMargin(!1),_.renderer.setShowGutter(!1),_.renderer.setHighlightGutterLine(!1),_.$mouseHandler.$focusTimeout=0,_.$highlightTagPending=!0,_},v=function(){function C(y){var _=l.createElement("div"),b=$(_);y&&y.appendChild(_),_.style.display="none",b.renderer.content.style.cursor="default",b.renderer.setStyle("ace_autocomplete"),b.renderer.$textLayer.element.setAttribute("role",s),b.renderer.$textLayer.element.setAttribute("aria-roledescription",n("Autocomplete suggestions")),b.renderer.$textLayer.element.setAttribute("aria-label",n("Autocomplete suggestions")),b.renderer.textarea.setAttribute("aria-hidden","true"),b.setOption("displayIndentGuides",!1),b.setOption("dragDelay",150);var E=function(){};b.focus=E,b.$isFocused=!0,b.renderer.$cursorLayer.restartTimer=E,b.renderer.$cursorLayer.element.style.opacity="0",b.renderer.$maxLines=8,b.renderer.$keepTextAreaAtCursor=!1,b.setHighlightActiveLine(!1),b.session.highlight(""),b.session.$searchHighlight.clazz="ace_highlight-marker",b.on("mousedown",function(w){var L=w.getDocumentPosition();b.selection.moveToPosition(L),M.start.row=M.end.row=L.row,w.stop()});var x,O=new u(-1,0,-1,1/0),M=new u(-1,0,-1,1/0);M.id=b.session.addMarker(M,"ace_active-line","fullLine"),b.setSelectOnHover=function(w){w?O.id&&(b.session.removeMarker(O.id),O.id=null):O.id=b.session.addMarker(O,"ace_line-hover","fullLine")},b.setSelectOnHover(!1),b.on("mousemove",function(w){if(!x){x=w;return}if(!(x.x==w.x&&x.y==w.y)){x=w,x.scrollTop=b.renderer.scrollTop,b.isMouseOver=!0;var L=x.getDocumentPosition().row;O.start.row!=L&&(O.id||b.setRow(L),T(L))}}),b.renderer.on("beforeRender",function(){if(x&&O.start.row!=-1){x.$pos=null;var w=x.getDocumentPosition().row;O.id||b.setRow(w),T(w,!0)}}),b.renderer.on("afterRender",function(){var w=b.getRow(),L=b.renderer.$textLayer,q=L.element.childNodes[w-L.config.firstRow],A=document.activeElement;if(q!==b.selectedNode&&b.selectedNode&&(l.removeCssClass(b.selectedNode,"ace_selected"),A.removeAttribute("aria-activedescendant"),b.selectedNode.removeAttribute(p),b.selectedNode.removeAttribute("id")),b.selectedNode=q,q){l.addCssClass(q,"ace_selected");var I=o(w);q.id=I,L.element.setAttribute("aria-activedescendant",I),A.setAttribute("aria-activedescendant",I),q.setAttribute("role",c),q.setAttribute("aria-roledescription",n("item")),q.setAttribute("aria-label",b.getData(w).caption||b.getData(w).value),q.setAttribute("aria-setsize",b.data.length),q.setAttribute("aria-posinset",w+1),q.setAttribute("aria-describedby","doc-tooltip"),q.setAttribute(p,"true")}});var k=function(){T(-1)},T=function(w,L){w!==O.start.row&&(O.start.row=O.end.row=w,L||b.session._emit("changeBackMarker"),b._emit("changeHoverMarker"))};b.getHoveredRow=function(){return O.start.row},r.addListener(b.container,"mouseout",function(){b.isMouseOver=!1,k()}),b.on("hide",k),b.on("changeSelection",k),b.session.doc.getLength=function(){return b.data.length},b.session.doc.getLine=function(w){var L=b.data[w];return typeof L=="string"?L:L&&L.value||""};var S=b.session.bgTokenizer;return S.$tokenizeRow=function(w){function L(D,W){D&&A.push({type:(q.className||"")+(W||""),value:D})}var q=b.data[w],A=[];if(!q)return A;typeof q=="string"&&(q={value:q});for(var I=q.caption||q.value||q.name,F=I.toLowerCase(),V=(b.filterText||"").toLowerCase(),R=0,B=0,N=0;N<=V.length;N++)if(N!=B&&(q.matchMask&1<=B?q="bottom":q="top"),q==="top"?(N.bottom=w.top-this.$borderSize,N.top=N.bottom-B):q==="bottom"&&(N.top=w.top+L+this.$borderSize,N.bottom=N.top+B);var D=N.top>=0&&N.bottom<=F;if(!A&&!D)return!1;D?R.$maxPixelHeight=null:q==="top"?R.$maxPixelHeight=j:R.$maxPixelHeight=P,q==="top"?(I.style.top="",I.style.bottom=F-N.bottom+"px",b.isTopdown=!1):(I.style.top=N.top+"px",I.style.bottom="",b.isTopdown=!0),I.style.display="";var W=w.left;return W+I.offsetWidth>V&&(W=V-I.offsetWidth),I.style.left=W+"px",I.style.right="",b.isOpen||(b.isOpen=!0,this._signal("show"),x=null),b.anchorPos=w,b.anchor=q,!0},b.show=function(w,L,q){this.tryShow(w,L,q?"bottom":void 0,!0)},b.goTo=function(w){var L=this.getRow(),q=this.session.getLength()-1;switch(w){case"up":L=L<=0?q:L-1;break;case"down":L=L>=q?-1:L+1;break;case"start":L=0;break;case"end":L=q}this.setRow(L)},b.getTextLeftOffset=function(){return this.$borderSize+this.renderer.$padding+this.$imageSize},b.$imageSize=0,b.$borderSize=1,b}return C}();l.importCssString(` +.ace_editor.ace_autocomplete .ace_marker-layer .ace_active-line { + background-color: #CAD6FA; + z-index: 1; +} +.ace_dark.ace_editor.ace_autocomplete .ace_marker-layer .ace_active-line { + background-color: #3a674e; +} +.ace_editor.ace_autocomplete .ace_line-hover { + border: 1px solid #abbffe; + margin-top: -1px; + background: rgba(233,233,253,0.4); + position: absolute; + z-index: 2; +} +.ace_dark.ace_editor.ace_autocomplete .ace_line-hover { + border: 1px solid rgba(109, 150, 13, 0.8); + background: rgba(58, 103, 78, 0.62); +} +.ace_completion-meta { + opacity: 0.5; + margin-left: 0.9em; +} +.ace_completion-message { + margin-left: 0.9em; + color: blue; +} +.ace_editor.ace_autocomplete .ace_completion-highlight{ + color: #2d69c7; +} +.ace_dark.ace_editor.ace_autocomplete .ace_completion-highlight{ + color: #93ca12; +} +.ace_editor.ace_autocomplete { + width: 300px; + z-index: 200000; + border: 1px lightgray solid; + position: fixed; + box-shadow: 2px 3px 5px rgba(0,0,0,.2); + line-height: 1.4; + background: #fefefe; + color: #111; +} +.ace_dark.ace_editor.ace_autocomplete { + border: 1px #484747 solid; + box-shadow: 2px 3px 5px rgba(0, 0, 0, 0.51); + line-height: 1.4; + background: #25282c; + color: #c1c1c1; +} +.ace_autocomplete .ace_text-layer { + width: calc(100% - 8px); +} +.ace_autocomplete .ace_line { + display: flex; + align-items: center; +} +.ace_autocomplete .ace_line > * { + min-width: 0; + flex: 0 0 auto; +} +.ace_autocomplete .ace_line .ace_ { + flex: 0 1 auto; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; +} +.ace_autocomplete .ace_completion-spacer { + flex: 1; +} +.ace_autocomplete.ace_loading:after { + content: ""; + position: absolute; + top: 0px; + height: 2px; + width: 8%; + background: blue; + z-index: 100; + animation: ace_progress 3s infinite linear; + animation-delay: 300ms; + transform: translateX(-100%) scaleX(1); +} +@keyframes ace_progress { + 0% { transform: translateX(-100%) scaleX(1) } + 50% { transform: translateX(625%) scaleX(2) } + 100% { transform: translateX(1500%) scaleX(3) } +} +@media (prefers-reduced-motion) { + .ace_autocomplete.ace_loading:after { + transform: translateX(625%) scaleX(2); + animation: none; + } +} +`,"autocompletion.css",!1),h.AcePopup=v,h.$singleLineEditor=$,h.getAriaId=o}),ace.define("ace/autocomplete/inline_screenreader",["require","exports","module"],function(e,h,m){var g=function(){function a(u){this.editor=u,this.screenReaderDiv=document.createElement("div"),this.screenReaderDiv.classList.add("ace_screenreader-only"),this.editor.container.appendChild(this.screenReaderDiv)}return a.prototype.setScreenReaderContent=function(u){for(!this.popup&&this.editor.completer&&this.editor.completer.popup&&(this.popup=this.editor.completer.popup,this.popup.renderer.on("afterRender",function(){var f=this.popup.getRow(),l=this.popup.renderer.$textLayer,n=l.element.childNodes[f-l.config.firstRow];if(n){for(var i="doc-tooltip ",o=0;o=0&&r.test(a[l]);l--)f.push(a[l]);return f.reverse().join("")},h.retrieveFollowingIdentifier=function(a,u,r){r=r||g;for(var f=[],l=u;l0)for(var b=this.popup.getFirstVisibleRow();b<=this.popup.getLastVisibleRow();b++){var E=this.popup.getData(b);E&&(!_||E.hideInlinePreview)&&this.$seen(E)}},y.prototype.$onPopupShow=function(_){this.$onPopupChange(_),this.stickySelection=!1,this.stickySelectionDelay>=0&&this.stickySelectionTimer.schedule(this.stickySelectionDelay)},y.prototype.observeLayoutChanges=function(){if(!(this.$elements||!this.editor)){window.addEventListener("resize",this.onLayoutChange,{passive:!0}),window.addEventListener("wheel",this.mousewheelListener);for(var _=this.editor.container.parentNode,b=[];_;)b.push(_),_.addEventListener("scroll",this.onLayoutChange,{passive:!0}),_=_.parentNode;this.$elements=b}},y.prototype.unObserveLayoutChanges=function(){var _=this;window.removeEventListener("resize",this.onLayoutChange,{passive:!0}),window.removeEventListener("wheel",this.mousewheelListener),this.$elements&&this.$elements.forEach(function(b){b.removeEventListener("scroll",_.onLayoutChange,{passive:!0})}),this.$elements=null},y.prototype.onLayoutChange=function(){if(!this.popup.isOpen)return this.unObserveLayoutChanges();this.$updatePopupPosition(),this.updateDocTooltip()},y.prototype.$updatePopupPosition=function(){var _=this.editor,b=_.renderer,E=b.layerConfig.lineHeight,x=b.$cursorLayer.getPixelPosition(this.base,!0);x.left-=this.popup.getTextLeftOffset();var O=_.container.getBoundingClientRect();x.top+=O.top-b.layerConfig.offset,x.left+=O.left-_.renderer.scrollLeft,x.left+=b.gutterWidth;var M={top:x.top,left:x.left};b.$ghostText&&b.$ghostTextWidget&&this.base.row===b.$ghostText.position.row&&(M.top+=b.$ghostTextWidget.el.offsetHeight);var k=_.container.getBoundingClientRect().bottom-E,T=kthis.filterText&&_.lastIndexOf(this.filterText,0)===0)var b=this.filtered;else var b=this.all;this.filterText=_,b=this.filterCompletions(b,this.filterText),b=b.sort(function(x,O){return O.exactMatch-x.exactMatch||O.$score-x.$score||(x.caption||x.value).localeCompare(O.caption||O.value)});var E=null;b=b.filter(function(x){var O=x.snippet||x.caption||x.value;return O===E?!1:(E=O,!0)}),this.filtered=b},y.prototype.filterCompletions=function(_,b){var E=[],x=b.toUpperCase(),O=b.toLowerCase();e:for(var M=0,k;k=_[M];M++){var T=!this.ignoreCaption&&k.caption||k.value||k.snippet;if(!!T){var S=-1,w=0,L=0,q,A;if(this.exactMatch){if(b!==T.substr(0,b.length))continue e}else{var I=T.toLowerCase().indexOf(O);if(I>-1)L=I;else for(var F=0;F=0&&(R<0||V0&&(S===-1&&(L+=10),L+=A,w|=1<",r.escapeHTML(x.caption),"","
",r.escapeHTML(i(x.snippet))].join(""))},id:"snippetCompleter"},s=[o,l,n];h.setCompleters=function(x){s.length=0,x&&s.push.apply(s,x)},h.addCompleter=function(x){s.push(x)},h.textCompleter=l,h.keyWordCompleter=n,h.snippetCompleter=o;var c={name:"expandSnippet",exec:function(x){return g.expandWithTab(x)},bindKey:"Tab"},p=function(x,O){$(O.session.$mode)},$=function(x){typeof x=="string"&&(x=u.$modes[x]),!!x&&(g.files||(g.files={}),v(x.$id,x.snippetFileId),x.modes&&x.modes.forEach($))},v=function(x,O){!O||!x||g.files[x]||(g.files[x]={},u.loadModule(O,function(M){!M||(g.files[x]=M,!M.snippets&&M.snippetText&&(M.snippets=g.parseSnippetFile(M.snippetText)),g.register(M.snippets||[],M.scope),M.includeScopes&&(g.snippetMap[M.scope].includeScopes=M.includeScopes,M.includeScopes.forEach(function(k){$("ace/mode/"+k)})))}))},C=function(x){var O=x.editor,M=O.completer&&O.completer.activated;if(x.command.name==="backspace")M&&!f.getCompletionPrefix(O)&&O.completer.detach();else if(x.command.name==="insertstring"&&!M){y=x;var k=x.editor.$liveAutocompletionDelay;k?_.delay(k):b(x)}},y,_=r.delayedCall(function(){b(y)},0),b=function(x){var O=x.editor,M=f.getCompletionPrefix(O),k=f.triggerAutocomplete(O);if(M&&M.length>=O.$liveAutocompletionThreshold||k){var T=a.for(O);T.autoShown=!0,T.showPopup(O)}},E=e("../editor").Editor;e("../config").defineOptions(E.prototype,"editor",{enableBasicAutocompletion:{set:function(x){x?(this.completers||(this.completers=Array.isArray(x)?x:s),this.commands.addCommand(a.startCommand)):this.commands.removeCommand(a.startCommand)},value:!1},enableLiveAutocompletion:{set:function(x){x?(this.completers||(this.completers=Array.isArray(x)?x:s),this.commands.on("afterExec",C)):this.commands.off("afterExec",C)},value:!1},liveAutocompletionDelay:{initialValue:0},liveAutocompletionThreshold:{initialValue:0},enableSnippets:{set:function(x){x?(this.commands.addCommand(c),this.on("changeMode",p),p(null,this)):(this.commands.removeCommand(c),this.off("changeMode",p))},value:!1}})}),function(){ace.require(["ace/ext/language_tools"],function(e){t&&(t.exports=e)})}()})(extLanguage_tools);const VARIANT_FORM_VERSION="3.0.10",MOCK_CASE_URL="https://ks3-cn-beijing.ksyuncs.com/vform-static/vcase/",ACE_BASE_PATH="https://ks3-cn-beijing.ksyun.com/vform2021/ace-mini",BEAUTIFIER_PATH="https://ks3-cn-beijing.ksyun.com/vform2021/js-beautify/1.14.0/beautifier.min.js";var index_vue_vue_type_style_index_0_scoped_true_lang$4="";const _sfc_main$2B={name:"CodeEditor",props:{modelValue:{type:String},readonly:{type:Boolean,default:!1},mode:{type:String,default:"javascript"},userWorker:{type:Boolean,default:!0}},emits:["update:modelValue"],mounted(){ace$1.config.set("basePath",ACE_BASE_PATH),this.addAutoCompletion(ace$1),this.aceEditor=ace$1.edit(this.$refs.ace,{maxLines:20,minLines:5,fontSize:12,theme:this.themePath,mode:this.modePath,tabSize:2,readOnly:this.readonly,highlightActiveLine:!0,value:this.codeValue}),this.aceEditor.setOptions({enableBasicAutocompletion:!0,enableSnippets:!0,enableLiveAutocompletion:!0}),this.mode==="json"?this.setJsonMode():this.mode==="css"&&this.setCssMode(),this.userWorker||this.aceEditor.getSession().setUseWorker(!1),this.aceEditor.getSession().on("change",t=>{this.$emit("update:modelValue",this.aceEditor.getValue())})},data(){return{aceEditor:null,themePath:"ace/theme/sqlserver",modePath:"ace/mode/javascript",codeValue:this.modelValue}},watch:{},methods:{addAutoCompletion(t){let d=[{meta:"VForm API",caption:"getWidgetRef",value:"getWidgetRef()",score:1},{meta:"VForm API",caption:"getFormRef",value:"getFormRef()",score:1}];t.require("ace/ext/language_tools").addCompleter({getCompletions:function(h,m,g,a,u){return a.length===0?u(null,[]):u(null,d)}})},setJsonMode(){this.aceEditor.getSession().setMode("ace/mode/json")},setCssMode(){this.aceEditor.getSession().setMode("ace/mode/css")},getEditorAnnotations(){return this.aceEditor.getSession().getAnnotations()},setValue(t){this.aceEditor.getSession().setValue(t)}}},_hoisted_1$s={class:"ace-container"},_hoisted_2$k={class:"ace-editor",ref:"ace"};function _sfc_render$2B(t,d,e,h,m,g){return require$$0$1.openBlock(),require$$0$1.createElementBlock("div",_hoisted_1$s,[require$$0$1.createElementVNode("div",_hoisted_2$k,null,512)])}var CodeEditor=_export_sfc$1(_sfc_main$2B,[["render",_sfc_render$2B],["__scopeId","data-v-335e1214"]]);const generateCode=function(t,d="vue"){let e=JSON.stringify(t);return d==="html"?` + + + + + VForm Demo + + + + + + +
+ + + Submit +
+ + diff --git a/src/api/database/index.ts b/src/api/database/index.ts new file mode 100644 index 0000000..9758cef --- /dev/null +++ b/src/api/database/index.ts @@ -0,0 +1,52 @@ +import { defHttp } from '@/utils/http/axios'; +import { AccountListGetResultModel, AccountListItem, AccountParams } from './model/index'; + +enum Api { + GETDATABASETABLEPAGE_LIST = '/api/SysDatabaseLink/LoadDataBaseInfo', //获取数据库 + ADDDATABASETABLE = '/api/SysDatabaseLink/AddBaseLinkForm', //新增数据库 + EDITDATABASETABLE = '/api/SysDatabaseLink/UpdateBaseLink?keyValue=', //编辑数据库 + DELETEDATABASETABLE = '/api/SysDatabaseLink/DeleteBaseLink?id=', //删除数据库 + GETDATABASEDETAIL = '/api/SysDatabaseLink/GetDataBaseForm', //编辑时获取详情数据 + TEStCONNECTTION = '/api/SysDatabaseLink/TestConnection', //测试连接串是否正确 + createPicTable = '/api/createTable/createTable', //图形化建表 + updateTable = '/api/CreateTable/UpdateTable', //图形化建表-修改 + loadTableRecordInfo = '/api/CreateTable/LoadTableRecordInfo', //图形化建表记录 + CheckTableExist = '/api/CreateTable/CheckTableExist', //图形化建表-新建检查 +} + +/** + * @description: Get sample options value + */ + +export const getDataBasePageList = (params: AccountParams) => + defHttp.get({ url: Api.GETDATABASETABLEPAGE_LIST, params }); + +export const getDataBaseDetail = (params: AccountParams) => + defHttp.get({ url: Api.GETDATABASEDETAIL, params }); + +export const testDataBaseConnection = (params: AccountParams) => + defHttp.get({ url: Api.TEStCONNECTTION, params }); + +export const addDataBaseInfo = (params: AccountListItem) => + defHttp.post({ url: Api.ADDDATABASETABLE, params }); + +export const editDataBaseInfo = (params: AccountListItem) => + defHttp.post({ + url: Api.EDITDATABASETABLE + params.databaseLinkId, + params, + }); + +export const delDataBaseInfo = (params: AccountListItem) => + defHttp.post({ url: Api.DELETEDATABASETABLE + params.id, params }); + +export const createPicTable = (params: AccountListItem) => + defHttp.post({ url: Api.createPicTable, params }); + +export const updateTable = (params: AccountParams) => + defHttp.post({ url: Api.updateTable, params }); + +export const loadTableRecordInfo = (params: AccountParams) => + defHttp.get({ url: Api.loadTableRecordInfo, params }); + +export const CheckTableExist = (params: AccountParams) => + defHttp.get({ url: Api.CheckTableExist, params }); diff --git a/src/api/database/model/index.ts b/src/api/database/model/index.ts new file mode 100644 index 0000000..c3638c5 --- /dev/null +++ b/src/api/database/model/index.ts @@ -0,0 +1,22 @@ +import { BasicFetchResult } from '@/api/model/baseModel'; + +export interface AccountListItem { + databaseLinkId: string; + dbName: string; + dbAlias: string; + dbType: number; + serverAddress: string; + dbConnection: string; + description: string; +} +/** + * @description: Request list return value + */ +export interface AccountParams { + id?: string; + keyword?: string; + page?: string; + limit?: string; +}; + +export type AccountListGetResultModel = BasicFetchResult; diff --git a/src/api/demo/account.ts b/src/api/demo/account.ts new file mode 100644 index 0000000..d4d9c27 --- /dev/null +++ b/src/api/demo/account.ts @@ -0,0 +1,16 @@ +import { defHttp } from '@/utils/http/axios'; +import { GetAccountInfoModel } from './model/accountModel'; + +enum Api { + ACCOUNT_INFO = '/account/getAccountInfo', + SESSION_TIMEOUT = '/user/sessionTimeout', + TOKEN_EXPIRED = '/user/tokenExpired', +} + +// Get personal center-basic settings + +export const accountInfoApi = () => defHttp.get({ url: Api.ACCOUNT_INFO }); + +export const sessionTimeoutApi = () => defHttp.post({ url: Api.SESSION_TIMEOUT }); + +export const tokenExpiredApi = () => defHttp.post({ url: Api.TOKEN_EXPIRED }); diff --git a/src/api/demo/cascader.ts b/src/api/demo/cascader.ts new file mode 100644 index 0000000..198853d --- /dev/null +++ b/src/api/demo/cascader.ts @@ -0,0 +1,9 @@ +import { defHttp } from '@/utils/http/axios'; +import { AreaModel, AreaParams } from '@/api/demo/model/areaModel'; + +enum Api { + AREA_RECORD = '/cascader/getAreaRecord', +} + +export const areaRecord = (data: AreaParams) => + defHttp.post({ url: Api.AREA_RECORD, data }); diff --git a/src/api/demo/casetypemodification.ts b/src/api/demo/casetypemodification.ts new file mode 100644 index 0000000..8d7fa02 --- /dev/null +++ b/src/api/demo/casetypemodification.ts @@ -0,0 +1,59 @@ +import { defHttp } from '@/utils/http/axios'; + +enum Api { + // 修改地类类型(仅限农用地到建设用地,待接收状态) + UpdateCaseinfoTypeKC = '/api/WFTask/UpdateCaseinfoTypeKC', + // 获取任务列表(地类类型修改专用) + GetTaskList = '/api/WFTask/GetTaskList', + // 获取任务日志列表(地类类型修改专用) + GetTaskLogList = '/api/WFTask/GetTaskLogList', + // 删除任务(地类类型修改专用) + DeleteTaskByIds = '/api/WFTask/DeleteTaskByIds', + // 删除任务日志(地类类型修改专用) + DeleteTaskLogByIds = '/api/WFTask/DeleteTaskLogByIds', + // 更新任务(地类修改专用) + UpdateTask = '/api/WFTask/UpdateTask', + // 更新任务日志(地类修改专用) + UpdateTaskLog = '/api/WFTask/UpdateTaskLog' +} + +export function UpdateCaseinfoTypeKC(caseno) { + return defHttp.post({ + url: `${Api.UpdateCaseinfoTypeKC}?caseno=${caseno}`, + }); +} +export function GetTaskList(params) { + return defHttp.get({ + url: Api.GetTaskList, + params + }); +} +export function GetTaskLogList(params) { + return defHttp.get({ + url: Api.GetTaskLogList, + params + }); +} +export function DeleteTaskByIds(ids) { + return defHttp.post({ + url: `${Api.DeleteTaskByIds}?ids=${ids}`, + }); +} +export function DeleteTaskLogByIds(ids) { + return defHttp.post({ + url: `${Api.DeleteTaskLogByIds}?ids=${ids}`, + }); +} +export function UpdateTask(data) { + return defHttp.post({ + url: Api.UpdateTask, + data + }); +} +export function UpdateTaskLog(data) { + return defHttp.post({ + url: Api.UpdateTaskLog, + data + }); +} + diff --git a/src/api/demo/cloudQuery.ts b/src/api/demo/cloudQuery.ts new file mode 100644 index 0000000..b7bb2d1 --- /dev/null +++ b/src/api/demo/cloudQuery.ts @@ -0,0 +1,66 @@ +import { defHttp } from '@/utils/http/axios'; + +enum Api { + // 添加云查询任务 + AddDroneTask = '/api/DroneCloudQuery/AddDroneTask', + // 根据云查询ID获取查询结果 + LoadCloudQueryById = '/api/DroneCloudQuery/LoadCloudQueryById', + // 获取全部地类数据 + LoadLandType = '/api/DroneCloudQuery/getLandType', + // 添加地类分割任务 + AddDroneLandTask = '/api/DroneCloudQuery/AddDroneLandTask', + // 根据云查询ID获取地类分割结果 + LoadCloudLandQueryById = '/api/DroneCloudQuery/LoadCloudLandQueryById', + // 查询云查询记录的情况 + LoadCloudQueryByCaseNo = '/api/DroneCloudQuery/LoadCloudQueryByCaseNo', + // 查询云查询全部记录的情况 + LoadCloudQueryAll = '/api/DroneCloudQuery/LoadCloudQueryAll', +} + +export function AddDroneTask(params: { geomid: string; caseno: string; countyname: string }) { + return defHttp.post({ + url: Api.AddDroneTask + '?geomid=' + params.geomid + '&caseno=' + params.caseno + '&countyName=' + params.countyname, + params, + }); +} + +export function LoadCloudQueryById(params: { id: string }) { + return defHttp.get({ + url: Api.LoadCloudQueryById, + params, + }); +} + +export function LoadLandType(params) { + return defHttp.get({ + url: Api.LoadLandType, + params, + }); +} + +export function AddDroneLandTask(params) { + return defHttp.post({ + url: Api.AddDroneLandTask, + params, + }); +} + +export function LoadCloudLandQueryById(params: { id: string }) { + return defHttp.get({ + url: Api.LoadCloudLandQueryById, + params, + }); +} + +export function LoadCloudQueryByCaseNo(params) { + return defHttp.get({ + url: Api.LoadCloudQueryByCaseNo + '?geomid=' + params.geomid + '&caseno=' + params.caseno, + }); +} + +export function LoadCloudQueryAll(params) { + return defHttp.get({ + url: Api.LoadCloudQueryAll, + params, + }); +} \ No newline at end of file diff --git a/src/api/demo/dbsource.ts b/src/api/demo/dbsource.ts new file mode 100644 index 0000000..909d272 --- /dev/null +++ b/src/api/demo/dbsource.ts @@ -0,0 +1,51 @@ +import { responsesmodel, LoadDataBaseInfoModel, AddOrUpdateFormModel } from './model/dbsourceModel'; +import { defHttp } from '@/utils/http/axios'; + +enum Api { + // 分页获取列表数据 + Get_LoadDataBaseInfo = '/api/DataSource/LoadDataBaseInfo', + // 获取数据源列名 + Get_GetDataColName = '/api/DataSource/GetDataColName', + // 新增或者修改数据源 + Post_AddOrUpdateForm = '/api/DataSource/AddOrUpdateForm', + // 删除数据源 + Post_DeleteEntity = '/api/DataSource/DeleteEntity', +} + +// 分页获取列表数据 +export function fun_LoadDataBaseInfo(params) { + return defHttp.get({ + url: Api.Get_LoadDataBaseInfo, + params, + }); +} + +// 获取数据源列名 +export function fun_GetDataColName(params) { + return defHttp.get({ + url: Api.Get_GetDataColName + '?code=' + params.code, + }); +} + +// 新增数据源 +export function fun_AddForm(params: AddOrUpdateFormModel) { + return defHttp.post({ + url: Api.Post_AddOrUpdateForm, + params, + }); +} + +// 修改数据源 +export function fun_UpdateForm(params: AddOrUpdateFormModel) { + return defHttp.post({ + url: Api.Post_AddOrUpdateForm + '?id=' + params.id, + params, + }); +} + +// 删除数据源 +export function fun_DeleteEntity(params) { + return defHttp.post({ + url: Api.Post_DeleteEntity + '?keyValue=' + params.keyValue, + }); +} diff --git a/src/api/demo/error.ts b/src/api/demo/error.ts new file mode 100644 index 0000000..0a7f662 --- /dev/null +++ b/src/api/demo/error.ts @@ -0,0 +1,12 @@ +import { defHttp } from '@/utils/http/axios'; + +enum Api { + // The address does not exist + Error = '/error', +} + +/** + * @description: Trigger ajax error + */ + +export const fireErrorApi = () => defHttp.get({ url: Api.Error }); diff --git a/src/api/demo/files.ts b/src/api/demo/files.ts new file mode 100644 index 0000000..5ef9e78 --- /dev/null +++ b/src/api/demo/files.ts @@ -0,0 +1,75 @@ +import { responsesmodel } from './model/queryModal'; +import { defHttp } from '@/utils/http/axios'; +import { BasicFetchResult } from '@/api/model/baseModel'; +import { UploadFileParams } from '#/axios'; +import { AxiosProgressEvent } from 'axios'; +import { useGlobSetting } from '@/hooks/setting'; + +// files +export interface files { + id: string; + folderId: string; + fileName: string; + filePath: string; + description: string; + fileType: string; + fileSize: string; + extension: string; + enable: boolean; + sortCode: number; + deleteMark: false; + createUserId: string; + createUserName: string; + createTime: string; + thumbnail: string; + belongApp: string; + belongAppId: string; +} +export type filesModel = BasicFetchResult; + +export interface UploadApiResult { + message: string; + code: number; + url: string; +} + +enum Api { + // 加载附件列表 + Get_Load = '/api/Files/Load', + // 删除附件 + Post_Delete = '/api/Files/Delete', + // 批量上传文件接口
客户端文本框需设置name='files' + Post_Upload = '/api/Files/Upload', +} + +const { apiUrl } = useGlobSetting(); + +// 加载附件列表 +export function fun_Load(params) { + return defHttp.get({ + url: Api.Get_Load, + params, + }); +} +// 删除附件 +export function fun_Delete(params) { + return defHttp.post({ + url: Api.Post_Delete, + params, + }); +} + +// 批量上传文件接口
客户端文本框需设置name='files' +export function fun_Upload( + params: UploadFileParams, + onUploadProgress: (progressEvent: AxiosProgressEvent) => void, +) { + return defHttp.uploadFile( + { + url: apiUrl + Api.Post_Upload, + onUploadProgress, + timeout: 300000, + }, + params, + ); +} diff --git a/src/api/demo/formModule.ts b/src/api/demo/formModule.ts new file mode 100644 index 0000000..235c16a --- /dev/null +++ b/src/api/demo/formModule.ts @@ -0,0 +1,90 @@ +import { + AccountParams, + responsesmodel, + getPageList_ParamsModel, + getPageListModel, + stateModel, + GetFormModel, + formModuleModel, + SysDataItemLoadModel, +} from './model/formModuleModel'; +import { defHttp } from '@/utils/http/axios'; + +enum Api { + // 获取分页列表 + Get_GetPageList = '/api/FormModule/GetPageList', + // 更新状态 + Post_UpdateModuleState = '/api/FormModule/UpdateModuleState', + // 删除实体数据(表单发布模板id) + Post_DeleteForm = '/api/FormModule/DeleteForm', + // 根据主键获取实体数据(编辑时使用) + Get_GetForm = '/api/FormModule/GetForm', + // 新增实体数据 + Post_AddForm = '/api/FormModule/AddForm', + // 编辑实体数据 + Post_UpdateForm = '/api/FormModule/UpdateForm', + // 获取字典分类列表 + Get_SysDataItemLoad = '/api/SysDataItem/Load', + // 判断数据表字段重复 + Get_ExistFiled = '/api/FormModule/ExistFiled', +} + +// 获取分页列表 +export function fun_GetPageList(params: getPageList_ParamsModel) { + return defHttp.get({ + url: Api.Get_GetPageList, + params, + }); +} + +// 更新状态 +export function fun_UpdateModuleState(params: stateModel) { + return defHttp.post({ + url: Api.Post_UpdateModuleState + '?id=' + params.id + '&state=' + params.state, + }); +} + +// 删除实体数据(表单发布模板id) +export function fun_DeleteForm(params: AccountParams) { + return defHttp.post({ + url: Api.Post_DeleteForm + '?keyValue=' + params.id, + }); +} + +// 根据主键获取实体数据(编辑时使用) +export function fun_GetForm(params) { + return defHttp.get({ + url: Api.Get_GetForm, + params, + }); +} + +// 新增实体数据 +export function Post_AddForm(params: formModuleModel) { + return defHttp.post({ + url: Api.Post_AddForm, + params, + }); +} +// 编辑实体数据 +export function Post_UpdateForm(params: formModuleModel) { + return defHttp.post({ + url: Api.Post_UpdateForm + '?id=' + params.formModuleEntity.id, + params, + }); +} + +// 获取字典分类列表 +export function Get_SysDataItemLoad() { + return defHttp.get({ + url: Api.Get_SysDataItemLoad, + }); +} + +// 判断数据表字段重复 +export function Get_Get_ExistFiled(params) { + return defHttp.get({ + url: Api.Get_ExistFiled, + params, + }); +} diff --git a/src/api/demo/formScheme.ts b/src/api/demo/formScheme.ts new file mode 100644 index 0000000..b533531 --- /dev/null +++ b/src/api/demo/formScheme.ts @@ -0,0 +1,313 @@ +import { + responsesModel, + AccountParams, + FromSortModel, + LoadFormPageModel, + FromSchemeInfoModel, + FromSchemeModel, + FromSchemandAndInfoModel, + stateModel, + schemeModel, + dataColNameModel, + schemePageListModel, + CodeTable_LoadCodeTablePage_Parameters_Model, + CodeTable_LoadCodeTablePage_Responses_Model, + CodeTable_GetForms_Parameters_Model, + CodeTable_GetForms_Responses_Model, + getTableList_Model, + CodeTable_ImportTable_Responses_Model, + ShpLayerSourceLoadPage_Model, +} from './model/formSchemeModel'; +import { defHttp } from '@/utils/http/axios'; + +enum Api { + // 字典 FormSort + LoadFormSort = '/api/SysDataItemDetail/Load?code=FormSort', + AddFormSort = '/api/SysDataItemDetail/Add', + UpdateFormSort = '/api/SysDataItemDetail/Update', + DeleteFormSort = '/api/SysDataItemDetail/Delete', + + // 表单设计 + // 查询表单分页信息 + LoadFormPage = '/api/FormScheme/LoadFormPage', + // LoadFormPage = '/api/FormScheme/LoadFormPage?pageIndex=1&pageSize=10', + // 新增自定义表单 + AddForm = '/api/FormScheme/AddForm', + // 获取自定义表单设计数据 + GetForm = '/api/FormScheme/GetForm', + // 获取自定义表单基本信息 + GetSchemeInfoEntity = '/api/FormScheme/GetSchemeInfoEntity', + // 更新自定义表单 + UpdateForm = '/api/FormScheme/UpdateForm', + // 启用或者停用表单 + UpdateState = '/api/FormScheme/UpdateState', + // 启用或者停用表单 + UpdateScheme = '/api/FormScheme/UpdateScheme', + // 删除自定义列表 + DeleteForm = '/api/FormScheme/DeleteForm', + // 获取数据源列表 + GetDataColName = '/api/FormScheme/GetDataColName', + // 获取自定义表单预览 + GetPreviewForm = '/api/FormScheme/GetPreviewForm', + // 获取自定义表单模板历史数据 + GetSchemePageList = '/api/FormScheme/GetSchemePageList', + // 获取表单分页数据 + GetFormDataPage = '/api/FormScheme/GetFormDataPage', + // 获取表单分页数据 + GetFormDataList = '/api/FormScheme/GetFormDataList', + // 获取表单数据 + GetFormDataFormScheme = '/api/FormScheme/GetFormData', + // 保存自定表单数据 + saveForm = '/api/FormScheme/SaveForm', + + // CodeTable 数据对象模型管理 + // 获取CodeTable的分页数据 + Get_LoadCodeTablePage = '/api/CodeTable/LoadCodeTablePage', + // 获取字典分类列表 + Get_GetEntitys = '/api/CodeTable/GetEntitys', + // 获取表的对象集合数据 + Get_GetForms = '/api/CodeTable/GetForms', + // 导入表的数据 + Post_ImportTable = '/api/CodeTable/ImportTable?dbcode=lrsystemdb', + // 导入获取数据库的表 + Get_GetTableList = '/api/FormModule/GetTableList', + LoadFormScheme = '/api/FormScheme/LoadFormScheme', + + // 创建表信息 + AddTable = '/api/DbTable/AddTable', + // 创建字段 + AddColumn = '/api/DbTable/AddColumn', + // 图斑组件-图层列表 + ShpLayerSourceLoadPage = '/api/ShpLayerSource/LoadPage', + // 图斑组件-图层列表-图层选择后-查找字段名 + GetTableAndViewColumnList = '/api/CodeTable/GetTableAndViewColumnList', +} + +// 字典 FormSort +export function functionLoadFormSort(params: AccountParams) { + return defHttp.get({ + url: Api.LoadFormSort, + params, + }); +} + +export function functionAddFormSort(params: FromSortModel) { + return defHttp.post({ + url: Api.AddFormSort + '?code=FormSort', + params, + }); +} + +export function functionUpdateFormSort(params: FromSortModel) { + return defHttp.post({ + url: Api.UpdateFormSort, + params, + }); +} + +export function functionDeleteFormSort(params: AccountParams) { + return defHttp.post({ + url: Api.DeleteFormSort + '?id=' + params.id, + }); +} + +// 表单设计 +// 查询表单分页信息 +export function functionLoadFormPage(params: LoadFormPageModel) { + return defHttp.get({ + url: Api.LoadFormPage, + params, + }); +} + +// 新增自定义表单 +export function functionAddForm(params: FromSchemandAndInfoModel) { + return defHttp.post({ + url: Api.AddForm, + params, + }); +} + +// 获取自定义表单设计数据 +export function functionGetForm(params: AccountParams) { + return defHttp.get({ + url: Api.GetForm, + params, + }); +} + +// 获取自定义表单基本信息 +export function functionGetSchemeInfoEntity(params: AccountParams) { + return defHttp.get({ + url: Api.GetSchemeInfoEntity, + params, + }); +} + +// 更新自定义表单 +export function functionUpdateForm(params: AccountParams) { + return defHttp.post({ + url: Api.UpdateForm + '?id=' + params.info.id, + params, + }); +} + +// 启用或者停用表单 +export function functionUpdateState(params: stateModel) { + return defHttp.post({ + url: Api.UpdateState + '?id=' + params.id + '&state=' + params.state, + }); +} + +// 启用或者停用历史表单 +export function functionUpdateScheme(params: schemeModel) { + return defHttp.post({ + url: Api.UpdateScheme + '?id=' + params.id + '&schemeId=' + params.schemeId, + }); +} + +// 删除自定义列表 +export function functionDeleteForm(params: AccountParams) { + return defHttp.post({ + url: Api.DeleteForm + '?id=' + params.id, + }); +} + +// 获取数据源列表 +export function functionGetDataColName(params: dataColNameModel) { + return defHttp.post({ + url: Api.GetDataColName + '?dbcode=' + params.dbcode + '&sql=' + params.sql, + }); +} + +// 获取自定义表单预览 +export function functionGetPreviewForm(params: AccountParams) { + return defHttp.get({ + url: Api.GetPreviewForm + '?keyValue=' + params.keyValue, + }); +} + +// 获取自定义表单模板历史数据 +export function functionGetSchemePageList(params: schemePageListModel) { + return defHttp.get({ + url: Api.GetSchemePageList, + params, + }); +} + +// CodeTable 数据对象模型管理 +// 获取CodeTable的分页数据 +export function function_Get_LoadCodeTablePage( + params: CodeTable_LoadCodeTablePage_Parameters_Model, +) { + return defHttp.get({ + url: + Api.Get_LoadCodeTablePage + + '?pageIndex=' + + params.page + + '&pageSize=' + + params.limit + + '&dbCode=' + + params.dbCode, + }); +} + +// // 获取表的对象集合数据 +// export function function_Get_GetEntitys() { +// return defHttp.get({ +// url: Api.Get_GetEntitys, +// }); +// } + +// 获取字典分类列表/api/CodeTable/GetForms +export function function_Get_GetForms(params: CodeTable_GetForms_Parameters_Model) { + return defHttp.get({ + // url: Api.Get_GetForms + '?dbCode=' + params.dbCode + '&tableNames=' + params.tableNames, + url: Api.Get_GetForms, + params, + }); +} + +// 导入表的数据 +// 获取 +export function function_Get_GetTableList() { + return defHttp.get({ + url: Api.Get_GetTableList, + }); +} +// 导入 +export function function_Post_ImportTable(params: CodeTable_ImportTable_Responses_Model) { + return defHttp.post({ + url: Api.Post_ImportTable, + params, + }); +} +// LoadFormScheme +export function LoadFormScheme(params) { + return defHttp.get({ + url: Api.LoadFormScheme, + params, + }); +} + +// 创建表信息 +export function AddTable(params) { + return defHttp.post({ + url: Api.AddTable + '?dbCode=' + params.dbCode, + params, + }); +} + +// 创建字段 +export function AddColumn(params) { + return defHttp.post({ + url: Api.AddColumn + '?dbCode=' + params.dbCode, + params: params.dbColumn, + }); +} + +// 图斑组件-图层列表 +export function ShpLayerSourceLoadPage() { + return defHttp.get({ + url: Api.ShpLayerSourceLoadPage, + }); +} + +// 图斑组件-图层列表-图层选择后-查找字段名 +export function GetTableAndViewColumnList(params) { + return defHttp.get({ + url: Api.GetTableAndViewColumnList, + params, + }); +} + +// 获取表单分页数据 【先不写】 +export function functionGetFormDataPage(params: AccountParams) { + return defHttp.post({ + url: Api.GetFormDataPage, + params, + }); +} +// 获取表单分页数据【先不写】 +export function functionGetFormDataList(params: AccountParams) { + return defHttp.post({ + url: Api.GetFormDataList, + params, + }); +} + +// 获取表单数据【先不写】 +export function functionGetFormDataFormScheme(params: AccountParams) { + return defHttp.get({ + url: Api.GetFormDataFormScheme, + params, + }); +} + +// 保存自定表单数据【先不写】 +export function functionsaveForm(params: AccountParams) { + return defHttp.post({ + url: Api.saveForm, + params, + }); +} diff --git a/src/api/demo/message.ts b/src/api/demo/message.ts new file mode 100644 index 0000000..a31dc31 --- /dev/null +++ b/src/api/demo/message.ts @@ -0,0 +1,46 @@ +import { responsesmodel } from './model/queryModal'; +import { defHttp } from '@/utils/http/axios'; + +enum Api { + LoadSysImMsgList = '/api/ImMsg/LoadSysImMsgList', + VirtualDeleteEntitys = '/api/ImMsg/VirtualDeleteEntitys', + DeleteEntitys = '/api/ImMsg/DeleteEntitys', + ReadMsg = '/api/ImMsg/ReadMsg', + GetLastList = '/api/ImMsg/GetLastList', + GetInfoByContentId = '/api/ImMsg/GetInfoByContentId', +} + +export function loadSysImMsgList(params) { + return defHttp.get({ + url: Api.LoadSysImMsgList, + params, + }); +} +export function virtualDeleteEntitys(params) { + return defHttp.post({ + url: Api.VirtualDeleteEntitys, + params, + }); +} +export function deleteEntitys(params) { + return defHttp.post({ + url: Api.DeleteEntitys, + params, + }); +} +export function readMsg(params) { + return defHttp.post({ + url: Api.ReadMsg + '?id=' + params.id, + }); +} +export function getLastList(params) { + return defHttp.get({ + url: Api.GetLastList + '?userId=' + params.userId, + }); +} + +export function getInfoByContentId(params) { + return defHttp.get({ + url: Api.GetInfoByContentId + '?contentid=' + params.id, + }); +} diff --git a/src/api/demo/model/accountModel.ts b/src/api/demo/model/accountModel.ts new file mode 100644 index 0000000..4594393 --- /dev/null +++ b/src/api/demo/model/accountModel.ts @@ -0,0 +1,7 @@ +export interface GetAccountInfoModel { + email: string; + name: string; + introduction: string; + phone: string; + address: string; +} diff --git a/src/api/demo/model/areaModel.ts b/src/api/demo/model/areaModel.ts new file mode 100644 index 0000000..dfaa481 --- /dev/null +++ b/src/api/demo/model/areaModel.ts @@ -0,0 +1,12 @@ +export interface AreaModel { + id: string; + code: string; + parentCode: string; + name: string; + levelType: number; + [key: string]: string | number; +} + +export interface AreaParams { + parentCode: string; +} diff --git a/src/api/demo/model/dbsourceModel.ts b/src/api/demo/model/dbsourceModel.ts new file mode 100644 index 0000000..12a0ec0 --- /dev/null +++ b/src/api/demo/model/dbsourceModel.ts @@ -0,0 +1,47 @@ +import { BasicFetchResult } from '@/api/model/baseModel'; + +// 常用返回消息 +export interface responses { + message: string; + code: number; + result: boolean; +} +export type responsesmodel = BasicFetchResult; + +// 分页获取列表数据 +export interface LoadDataBaseInfo { + id: string; + code: string; + name: string; + dbId: string; + sql: string; + description: string; + createUserId: string; + createUserName: string; + createDate: string; + modifyUserId: string; + modifyUserName: string; + modifyDate: string; + tenantId: string; + isEdit: 0; +} +export type LoadDataBaseInfoModel = BasicFetchResult; + +// 新增或者修改数据源 +export interface AddOrUpdateForm { + id: string; + code: string; + name: string; + dbId: string; + sql: string; + description: string; + createUserId: string; + createUserName: string; + createDate: string; + modifyUserId: string; + modifyUserName: string; + modifyDate: string; + tenantId: string; + isEdit: number; +} +export type AddOrUpdateFormModel = BasicFetchResult; diff --git a/src/api/demo/model/formModuleModel.ts b/src/api/demo/model/formModuleModel.ts new file mode 100644 index 0000000..5512a3d --- /dev/null +++ b/src/api/demo/model/formModuleModel.ts @@ -0,0 +1,216 @@ +import { BasicPageParams, BasicFetchResult } from '@/api/model/baseModel'; + +// +export type AccountParams = BasicPageParams & { + account?: string; + nickname?: string; + [key: string]: any; +}; + +// 常用返回消息 +export interface responses { + message: string; + code: number; + result: boolean; +} +export type responsesmodel = BasicFetchResult; + +// 获取分页列表 +// 查询表单分页信息 +export interface getPageList_Params { + keyword: string; + pmoduleid: string; + page: number; + limit: number; + name: string; +} +export interface getPageList { + id: string; + code: string; + formCode: string; + formVerison: string; + icon: string; + name: string; + type: number; + pmoduleId: string; + moduleId: string; + sortCode: number; + enabledMark: number; + description: string; + createDate: string; + createUserId: string; + createUserName: string; + modifyDate: string; + modifyUserId: string; + modifyUserName: string; + scheme: string; + keyWord: string; + tenantId: string; + isMain: number; +} +export type getPageList_ParamsModel = BasicFetchResult; +export type getPageListModel = BasicFetchResult; + +// 更新状态 +export interface state { + id: string; + state: string; +} +export type stateModel = BasicFetchResult; + +// 删除实体数据(表单发布模板id) +// AccountParams + +// 根据主键获取实体数据(编辑时使用) +export interface form { + id: string; + code: string; + formCode: string; + formVerison: string; + icon: string; + name: string; + type: number; + pmoduleId: string; + moduleId: string; + sortCode: number; + enabledMark: number; + description: string; + createDate: string; + createUserId: string; + createUserName: string; + modifyDate: string; + modifyUserId: string; + modifyUserName: string; + scheme: string; + keyWord: string; + tenantId: string; + isMain: number; +} +export type GetFormModel = BasicFetchResult
; + +// 表单发布实体数据 +// 表单发布实体 +export interface formModuleEntity { + id: string; + code: string; + formCode: string; + formVerison: string; + icon: string; + name: string; + type: number; + pmoduleId: string; + moduleId: string; + sortCode: number; + enabledMark: number; + description: string; + createDate: string; + createUserId: string; + createUserName: string; + modifyDate: string; + modifyUserId: string; + modifyUserName: string; + scheme: string; + keyWord: string; + tenantId: string; + isMain: number; +} +export type formModuleEntityModel = BasicFetchResult; +// 表单发布实体 +export interface elements { + id: string; + domId: string; + name: string; + attr: string; + script: string; + icon: string; + class: string; + remark: string; + sort: number; + moduleId: string; +} +export interface sysModule { + id: string; + cascadeId: string; + name: string; + parentId: string; + parentName: string; + url: string; + iconName: string; + status: number; + sortNo: number; + code: string; + encode: string; + isSys: true; + elements: elements; +} +export type sysModuleModel = BasicFetchResult; +// 表单发布实体 +export interface sysModuleElement { + id: string; + domId: string; + name: string; + attr: string; + script: string; + icon: string; + class: string; + remark: string; + sort: number; + moduleId: string; +} +export type sysModuleElementModel = BasicFetchResult; +// 表单发布实体-Column +export interface sysModuleColumn { + moduleColumnId: string; + moduleId: string; + parentId: string; + encode: string; + fullName: string; + sortCode: number; + tenantId: string; + isMain: number; +} +export type sysModuleColumnModel = BasicFetchResult; +// 表单发布实体 +export interface sysModuleForm { + moduleFormId: string; + moduleId: string; + parentId: string; + encode: string; + fullName: string; + sortCode: number; + tenantId: string; + isMain: number; +} +export type sysModuleFormModel = BasicFetchResult; +// +export interface formModuleModel { + formModuleEntity: formModuleEntityModel; + sysModule: sysModuleModel; + sysModuleElement: sysModuleElementModel; + sysModuleColumn: sysModuleColumnModel; + sysModuleForm: sysModuleFormModel; +} + +// 获取字典分类列表 +// /api/SysDataItem/Load +export interface SysDataItemLoad { + itemId: string; + parentId: string; + itemCode: string; + itemName: string; + isTree: number; + isNav: number; + sortCode: number; + deleteMark: number; + enabledMark: number; + description: string; + createDate: string; + createUserId: string; + createUserName: string; + modifyDate: string; + modifyUserId: string; + modifyUserName: string; + isEdit: 0; +} + +export type SysDataItemLoadModel = BasicFetchResult; diff --git a/src/api/demo/model/formSchemeModel.ts b/src/api/demo/model/formSchemeModel.ts new file mode 100644 index 0000000..09e760b --- /dev/null +++ b/src/api/demo/model/formSchemeModel.ts @@ -0,0 +1,235 @@ +import { BasicPageParams, BasicFetchResult } from '@/api/model/baseModel'; + +export interface responses { + message: string; + code: number; + result: boolean; +} + +export type responsesModel = BasicFetchResult; + +// 字典 FormSort +export interface FromSort { + itemDetailId: string; + itemId: string; + parentId: string; + itemCode: string | null; + itemName: string; + itemValue: string; + quickQuery: string; + simpleSpelling: string; + isDefault?: string | null; + sortCode: string; + deleteMark: string; + enabledMark: number; + description: string | null; + createDate: string; + createUserId: string | null; + createUserName: string | null; + modifyDate: string; + modifyUserId: string | null; + modifyUserName: string | null; +} + +// 查询表单分页信息 +export interface LoadFormPage { + keyWord: string; + category: string; + isEnabled: boolean; + pageIndex: number; + pageSize: number; + name: string; +} + +// 表单设计 +export interface FromSchemeInfo { + id: string; + name: string; + category: string; + schemeId: string; + enabledMark: number; + formType: number; + description: string; + type: number; + createUserName: string; + createUserId: string; + createDate: string; + tenantId: string; +} + +export interface FromScheme { + id: string; + schemeInfoId: string; + type: number; + scheme: string; + createDate: string; + createUserId: string; + createUserName: string; + tenantId: string; +} + +export interface dataColName { + dbCode: string; + sql: string; +} + +// 启用或者停用表单 +export interface state { + id: string; + state: string; +} +// 启用或者停用历史表单 +export interface scheme { + id: string; + schemeId: string; +} +// 获取自定义表单模板历史数据 +export interface schemePageList { + page: number; + limit: number; + key: string; + schemeInfoId: string; +} + +export type AccountParams = BasicPageParams & { + account?: string; + nickname?: string; + [key: string]: any; +}; + +// 字典 +export type FromSortModel = BasicFetchResult; +// 分页 +export type LoadFormPageModel = BasicFetchResult; +// 自定义表单 +export type FromSchemeInfoModel = BasicFetchResult; +export type FromSchemeModel = BasicFetchResult; +export type FromSchemandAndInfoModel = { + info: FromSchemeInfoModel; + scheme: FromSchemeModel; +}; +// 数据库数据 +export type dataColNameModel = BasicFetchResult; +// 启用或者停用表单 +export type stateModel = BasicFetchResult; +// 历史记录数据 +export type schemeModel = BasicFetchResult; +// 获取自定义表单模板历史数据 +export type schemePageListModel = BasicFetchResult; + +// ------------------------------------------------------------- +// CodeTable 数据对象模型管理 +// 获取CodeTable的分页数据 +export interface CodeTable_LoadCodeTablePage_Parameters { + keyWord: string; + dbCode: string; + pageIndex: number; + pageSize: number; +} + +export interface CodeTable_LoadCodeTablePage_Responses { + id: string; + className: string; + tableName: string; + dbId: string; + description: string; + isLock: number; + deleteMark: number; + state: number; + tenantId: string; +} + +// 获取字典分类列表 +// export interface CodeTable_GetForms_Parameters { +// dbCode: string; +// tableNames: string; +// } + +// // 获取表的对象集合数据 +export interface CodeTable_GetForms_Parameters { + dbCode: string; + tableNames: string; +} + +export interface db_codetable { + id: string; + className: string; + tableName: string; + dbId: string; + description: string; + isLock: number; + deleteMark: number; + state: number; + tenantId: string | null; +} + +export interface db_codecolumnsList { + id: string; + codeTableId: string; + dbColumnName: string; + description: string; + isIdentity: number; + isPrimaryKey: number; + isNullable: number; + csType: string; + dbType: string; + length: number; + decimalDigits: number; + sort: number; + tenantId: string | null; +} + +// // 获取表的对象集合数据 +// export interface CodeTable_ImportTable_Parameters { +// dbCode: string; +// tableNames: string; +// } +export interface getTableList { + name: string; + description: string; + dbObjectType: number; +} +export type getTableList_Model = BasicFetchResult; + +export interface codeTableStr { + codeTableStr: string; +} + +export type codeTableStr_Model = BasicFetchResult; + +export type CodeTable_ImportTable_Responses_Model = { + codeTableStr: codeTableStr_Model; + tableList: getTableList_Model; +}; + +// CodeTable 数据对象模型管理 +// 获取CodeTable的分页数据 +export type CodeTable_LoadCodeTablePage_Parameters_Model = + BasicFetchResult; + +export type CodeTable_LoadCodeTablePage_Responses_Model = + BasicFetchResult; + +// 获取字典分类列表 +export type CodeTable_GetForms_Parameters_Model = BasicFetchResult; + +export type db_codetable_Model = BasicFetchResult; +export type db_codecolumnsList_Model = BasicFetchResult; + +export type CodeTable_GetForms_Responses_Model = { + db_codetable: db_codetable_Model; + db_codecolumnsList: db_codecolumnsList_Model; +}; + +// 图斑组件-图层列表 +export interface ShpLayerSourceLoadPage { + id: string; + name: string; + description: string; + type: number; + image: string; + createTime: string; + createId: string; + relationTable: string; +} +export type ShpLayerSourceLoadPage_Model = BasicFetchResult; diff --git a/src/api/demo/model/optionsModel.ts b/src/api/demo/model/optionsModel.ts new file mode 100644 index 0000000..871ae9f --- /dev/null +++ b/src/api/demo/model/optionsModel.ts @@ -0,0 +1,15 @@ +import { BasicFetchResult } from '@/api/model/baseModel'; + +export interface DemoOptionsItem { + name: string; + id: string; +} + +export interface selectParams { + id: number | string; +} + +/** + * @description: Request list return value + */ +export type DemoOptionsGetResultModel = BasicFetchResult; diff --git a/src/api/demo/model/queryModal.ts b/src/api/demo/model/queryModal.ts new file mode 100644 index 0000000..689a650 --- /dev/null +++ b/src/api/demo/model/queryModal.ts @@ -0,0 +1,24 @@ +import { BasicFetchResult } from '@/api/model/baseModel'; + +// 常用返回消息 +export interface responses { + code: number; + columnHeaders: []; + count: number; + result: []; + msg: string; +} +export type responsesmodel = BasicFetchResult; + +export type droneCaseDealModel = { + video_list?: any; + pic_info_list?: any; + after_pic_list?: any; + remove_video_list?: any; + evidence_file_list?: any; + boundary_pic_list?: any; + punish_pic_list?: any; + payment_pic_list?: any; + agree_checkout_pic_list?: any; + checkout_pic_list?: any; +}; \ No newline at end of file diff --git a/src/api/demo/model/systemModel.ts b/src/api/demo/model/systemModel.ts new file mode 100644 index 0000000..b0350b5 --- /dev/null +++ b/src/api/demo/model/systemModel.ts @@ -0,0 +1,133 @@ +import { BasicPageParams, BasicFetchResult } from '@/api/model/baseModel'; + +export type AccountParams = BasicPageParams & { + account?: string; + nickname?: string; + [key: string]: any; +}; + +export type RoleParams = { + roleName?: string; + status?: string; +}; + +export type RolePageParams = BasicPageParams & RoleParams; + +export type DeptParams = { + deptName?: string; + status?: string; +}; + +export type MenuParams = { + menuName?: string; + status?: string; + id?: string; +}; + +export interface AccountListItem { + id: string; + account: string; + email: string; + nickname: string; + role: number; + createTime: string; + remark: string; + status: number; +} + +export interface DeptListItem { + id?: string; + orderNo?: string; + createTime?: string; + remark?: string; + status?: number; + roleId?: string; + moduleIds?: any; +} + +export interface MenuListItem { + id: string; + orderNo: string; + createTime: string; + status: number; + icon: string; + component: string; + permission: string; +} + +export interface RoleListItem { + id: string; + name: string; + roleName: string; + roleValue: string; + status: number; + orderNo: string; + createTime: string; +} +export interface addDept { + name: string; + parentId: string; + parentName: string; + status: number; +} +export interface PositionByOrgParams { + orgid: string; +} + +/** + * @description: Request list return value + */ +export type AccountListGetResultModel = BasicFetchResult; + +export type DeptListGetResultModel = BasicFetchResult; + +export type MenuListGetResultModel = BasicFetchResult; + +export type RolePageListGetResultModel = BasicFetchResult; + +export type RoleListGetResultModel = RoleListItem[]; + +export type addDeptModel = addDept[]; + +export type ReportParams = BasicPageParams; + +export interface ReportListItem { + id?:string +} + +export interface NoticeListItem { + Id :string; + msg_title:string; + msg_content:string; + createtime:string; + createuser:string; + createusername:string; + is_delete:number; + msg_type:number; + case_no:string; + caseid:string; + is_read:number; +} + +export interface UserListParams{ + key:string; + page:number; + limit:number; +} +export interface UserListItem{ + account:string; + name:string; + id:string; +} + +export type UserListGetResultModel = BasicFetchResult; + +export interface StatisticalListItem{ + account:string; + name:string; + id:string; +} + +export type StatisticalListGetResultModel = BasicFetchResult; + + diff --git a/src/api/demo/model/tableModel.ts b/src/api/demo/model/tableModel.ts new file mode 100644 index 0000000..8f1eea5 --- /dev/null +++ b/src/api/demo/model/tableModel.ts @@ -0,0 +1,20 @@ +import { BasicPageParams, BasicFetchResult } from '@/api/model/baseModel'; +/** + * @description: Request list interface parameters + */ +export type DemoParams = Partial; + +export interface DemoListItem { + id: string; + beginTime: string; + endTime: string; + address: string; + name: string; + no: number; + status: number; +} + +/** + * @description: Request list return value + */ +export type DemoListGetResultModel = BasicFetchResult; diff --git a/src/api/demo/query.ts b/src/api/demo/query.ts new file mode 100644 index 0000000..75ceeed --- /dev/null +++ b/src/api/demo/query.ts @@ -0,0 +1,86 @@ +import { responsesmodel, droneCaseDealModel } from './model/queryModal'; +import { defHttp } from '@/utils/http/axios'; + +enum Api { + // complete-分页获取列表数据 + Get_LoadCaseInfoList = '/api/DroneCaseinfo/LoadCaseInfoList', + // complete- + Get_LoadList = '/api/Categorys/LoadList', + // 获取数据字典明显根据分类编号 + Get_load = '/api/SysDataItemDetail/Load', + // complete- + // Get_OrgList = '/api/Orgs/OrgList', + Get_OrgList = '/api/Orgs/OrgsAllTree', + // complete-导出 + Get_ExportCaseInfoList = '/api/DroneCaseinfo/ExportCaseInfoList', + + // 图斑详情 + Get_getCaseInfo = '/api/DroneCaseinfo/GetCaseInfo', + // 获取图斑处理流程 + Get_GetCaseFlowLog = '/api/DroneCaseinfo/GetCaseFlowLog', + // 处理详情 + Get_GetDroneCaseDeal = '/api/DroneCaseinfo/GetDroneCaseDeal', +} + +// complete-分页获取列表数据 +export function fun_LoadDataBaseInfo(params) { + return defHttp.get({ + url: Api.Get_LoadCaseInfoList, + params, + }); +} + +// complete-分页获取列表数据 +export function fun_LoadList(params) { + return defHttp.get({ + url: Api.Get_LoadList, + params, + }); +} + +// 获取数据字典明显根据分类编号 +export function fun_load(params) { + return defHttp.get({ + url: Api.Get_load, + params, + }); +} + +// complete-分页获取列表数据 +export function fun_OrgList() { + return defHttp.get({ + url: Api.Get_OrgList, + }); +} + +// complete-导出 +export function fun_ExportCaseInfoList(params) { + return defHttp.get({ + url: Api.Get_ExportCaseInfoList, + params, + }); +} + +// 图斑详情 +export function fun_getCaseInfo(params) { + return defHttp.get({ + url: Api.Get_getCaseInfo, + params, + }); +} + +// 处理详情 +export function fun_GetCaseFlowLog(params) { + return defHttp.get({ + url: Api.Get_GetCaseFlowLog, + params, + }); +} + +// 获取图斑处理流程 +export function fun_GetDroneCaseDeal(params) { + return defHttp.get({ + url: Api.Get_GetDroneCaseDeal, + params, + }); +} diff --git a/src/api/demo/resubmit.ts b/src/api/demo/resubmit.ts new file mode 100644 index 0000000..d3e4632 --- /dev/null +++ b/src/api/demo/resubmit.ts @@ -0,0 +1,11 @@ +import { defHttp } from '@/utils/http/axios'; +enum Api { + SaveReSubmitInfo = '/api/ReSubmit/SaveReSubmitInfo', +} + +export function SaveReSubmitInfo(params:{originalcaseno: string, remark: string, subjectKey: string}) { + return defHttp.post({ + url: Api.SaveReSubmitInfo, + params, + }); +} \ No newline at end of file diff --git a/src/api/demo/select.ts b/src/api/demo/select.ts new file mode 100644 index 0000000..f5f5cf9 --- /dev/null +++ b/src/api/demo/select.ts @@ -0,0 +1,12 @@ +import { defHttp } from '@/utils/http/axios'; +import { DemoOptionsItem, selectParams } from './model/optionsModel'; + +enum Api { + OPTIONS_LIST = '/select/getDemoOptions', +} + +/** + * @description: Get sample options value + */ +export const optionsListApi = (params?: selectParams) => + defHttp.get({ url: Api.OPTIONS_LIST, params }); diff --git a/src/api/demo/system.ts b/src/api/demo/system.ts new file mode 100644 index 0000000..c224197 --- /dev/null +++ b/src/api/demo/system.ts @@ -0,0 +1,532 @@ +import { + AccountParams, + DeptListItem, + MenuParams, + RoleParams, + RolePageParams, + MenuListGetResultModel, + PositionByOrgParams, + DeptListGetResultModel, + AccountListGetResultModel, + RolePageListGetResultModel, + RoleListGetResultModel, + addDept, + ReportParams, + ReportListGetResultModel, + NoticeListGetResultModel, + UserListParams, + UserListGetResultModel, + StatisticalListGetResultModel, +} from './model/systemModel'; +import { defHttp } from '@/utils/http/axios'; + +enum Api { + DeptList = '/api/Orgs/OrgsTree', + AccountList = '/api/users/load', + AddAccount = '/api/Users/AddOrUpdate', + DeleteAccount = '/api/Users/Delete', + AddDept = '/api/Orgs/Add', + UpdateDept = '/api/Orgs/Update', + DeleteDept = '/api/Orgs/Delete', + OrgList = '/api/Orgs/LoadPage', + RolePageList = '/api/Roles/LoadPage', + AddRole = '/api/Roles/Add', + UpdateRole = '/api/Roles/Update', + DeleteRole = '/api/Roles/Delete', + MenuList = '/api/Modules/ModulesTree', + ButtonList = '/api/Modules/ElementsByModule', + AddMenu = '/api/Modules/Add', + AddButton = '/api/Modules/AddMenu', + EditMenu = '/api/Modules/Update', + EditButton = '/api/Modules/UpdateMenu', + DeleteMenu = '/api/Modules/Delete', + DeleteButton = '/api/Modules/DeleteMenu', + MenuDetail = '/api/Modules/ModuleById', + AllModuleDetail = '/api/Modules/AllModule', + PositionList = '/api/SysPosition/Load', + AddPosition = '/api/SysPosition/Add', + PosGroupList = '/api/SysPosGroup/Load', + AddPosGroup = '/api/SysPosGroup/Add', + PositionsTree = '/api/SysPosition/PositionsTree', + OrgPosGroup = '/api/Orgs/OrgPosGroup', + UserRoles = '/api/Users/UserRoles', + OrgPositonTree = '/api/Orgs/OrgPositonTree', + UserOrgs = '/api/Users/UserOrgs', + AssignModule = '/api/Roles/AssignModule', + LoadForRole = '/api/Modules/LoadForRole', + LoadByRole = '/api/Users/LoadByRole', + IsAccountExist = '/system/accountExist', + setRoleStatus = '/system/setRoleStatus', + GetAllRoleList = '/system/getAllRoleList', + LoadPositionByOrg = '/api/SysPosition/LoadPositionByOrg', + LoadDataBaseLinkTree = '/api/SysDatabaseLink/LoadDataBaseLinkTree', + GetPosInfo = '/api/SysPosition/Get', + UpdatePosition = '/api/SysPosition/Update', + ReportList = '/api/DroneCaseinfo/LoadCaseInfoList', + NoticeList = '/api/DroneCaseinfo/LoadMessageList', + AddNotice = '/api/DroneCaseinfo/AddMessage', + UpdateNotice = '/api/DroneCaseinfo/UpdateMessage', + DeleteNotice = '/api/DroneCaseinfo/UpdateDelMessage', + UserList = '/api/users/load', + // StatisticalList='/api/DroneCaseinfo/CaseSynthesisCensus', + StatisticalList = '/api/DroneCaseInfoSingle/CaseSynthesisCensusSingle', + StatisticalListExport = '/api/DroneCaseInfoSingle/ExportCaseSynthesisCensusStreet', + LoadNoticeDetail = '/api/DroneCaseinfo/LoadMessage', + getChildrenTree = '/api/Orgs/LoadChildren', + GetUserRoles = '/api/Roles/UserRoles', + GetUserOrgs = '/api/Orgs/UserOrgs', + GetSpecialData = '/api/Specialcolumn/GetDataColName', + LoadCaseInfoTuBanList = '/api/DroneCaseInfoSingle/LoadCaseInfoTuBanList', + LoadCaseInfoIllegalList = '/api/DroneCaseInfoSingle/LoadCaseInfoIllegalList', + CaseOffence = '/api/DroneCaseInfoSingle/CaseOffence', + LoadCaseInfoListOffence = '/api/DroneCaseInfoSingle/LoadCaseInfoListOffence', + DealIllegalCaseInfo = '/api/DroneCaseInfoSingle/dealIllegalCaseInfo', + // 修改图斑-获取图斑列表 + LoadCaseInfoListForUpdate = '/api/DroneCaseInfoSingle/LoadCaseInfoListForUpdate', + // 修改图斑-获取单个图斑信息 + LoadCaseInfoById = '/api/DroneCaseInfoSingle/LoadCaseInfoById', + // 修改图斑-修改图斑信息 + UpdateCaseInfo = '/api/DroneCaseInfoSingle/UpdateCaseInfo', + // 修改图斑-获取图斑历史信息 + LoadCaseHistoryInfoList = '/api/DroneCaseInfoSingle/LoadCaseHistoryInfoList', + // 成果管理-图层管理 + // geo服务增加 + ShpGeoLayerAdd = '/api/ShpGeoLayer/Add', + // geo列表 + ShpGeoLayerLoadPage = '/api/ShpGeoLayer/LoadPage', + // geo获取 + ShpGeoLayerGet = '/api/ShpGeoLayer/Get', + // geo更新 + ShpGeoLayerUpdateLayer = '/api/ShpGeoLayer/UpdateLayer', + // geo删除 + ShpGeoLayerDelete = '/api/ShpGeoLayer/Delete', + // geo解析shp文件 + ShpGeoLayerParseShpInfo = '/api/ShpGeoLayer/ParseShpInfo', + // 获取地图中心点 + getGeomData = '/api/ShpGeoLayer/GetGeomData', + // 通过表名和id获取该条数据 + getDataTableRecord = '/api/ShpGeoLayer/GetDataTableRecord', + // 成果管理-影像管理 + // 更新tiff影像 + GeoTiffManagerUpdateGeoTiff = '/api/GeoTiffManager/UpdateGeoTiff', + // 影像列表 + GeoTiffManagerLoadPage = '/api/GeoTiffManager/LoadPage', + // 影像单个获取 + GeoTiffManagerGet = '/api/GeoTiffManager/Get', + // 删除tiff影像 + DeleteTifStore = '/api/GeoTiffManager/DeleteTifStore', + // 更新tiff周的影像缩略图 + UpdateLayerGroupThumb = '/api/GeoTiffManager/UpdateLayerGroupThumb', + // 成果管理-航飞图片 + // 添加成果 + AchievementManageAddImageexif = '/api/AchievementManage/AddImageexif', + // 案件判读 + AchievementManageIntactById = '/api/AchievementManage/IntactById', + // 添加任务 + AchievementManageAddTask = '/api/AchievementManage/AddTask', + // 任务查询 + AchievementManageListTask = '/api/AchievementManage/ListTask', + // 任务查询个体 + AchievementManageListDroneShpImageexif = '/api/AchievementManage/ListDroneShpImageexif', + // 成果管理-图层样式 + // 添加 + GeoStyleAdd = '/api/GeoStyle/Add', + // 遍历 + GeoStylePage = '/api/GeoStyle/Page', + GeoStyleBindLayer = '/api/GeoStyle/BindLayer', + // 非法采矿-统计列表 + CaseOffenceMinerals = '/api/DroneCaseInfoMinerals/CaseOffenceMinerals', + // 非法采矿-统计列表New + CaseOffenceMineralsNew = '/api/DroneCaseInfoMinerals/CaseOffenceMineralsNew', +} +export const getPositionsTree = (params?: AccountParams) => + defHttp.get({ url: Api.PositionsTree, params }); + +export const getPositionList = (params: AccountParams) => + defHttp.get({ url: Api.PositionList, params }); + +export const getPosGroupList = (params?: AccountParams) => + defHttp.get({ url: Api.PosGroupList, params }); + +export const getAccountList = (params: AccountParams) => + defHttp.get({ url: Api.AccountList, params }); + +export const getDeptList = (params?: DeptListItem) => + defHttp.get({ url: Api.DeptList, params }); + +export const getOrgList = (params?: DeptListItem) => + defHttp.get({ url: Api.OrgList, params }); + +export const getOrgPositonTree = (params?: DeptListItem) => + defHttp.get({ url: Api.OrgPositonTree, params }); + +export const loadForRole = (params?: DeptListItem) => + defHttp.get({ url: Api.LoadForRole, params }); + +export const loadByRole = (params?: DeptListItem) => + defHttp.get({ url: Api.LoadByRole, params }); + +export const getChildrenTree = (params: { parentId: number }) => + defHttp.get({ url: Api.getChildrenTree, params }); + +export function addAccount(params) { + return defHttp.post({ + url: Api.AddAccount, + params, + }); +} +export function deleteAccount(params) { + return defHttp.post({ + url: Api.DeleteAccount, + params, + }); +} + +export function addPosGroup(params) { + return defHttp.post({ + url: Api.AddPosGroup, + params, + }); +} +export function orgPosGroup(params) { + return defHttp.post({ + url: Api.OrgPosGroup, + params, + }); +} +export function userRoles(params) { + return defHttp.post({ + url: Api.UserRoles, + params, + }); +} + +export function userOrgs(params) { + return defHttp.post({ + url: Api.UserOrgs, + params, + }); +} + +export function addPosition(params) { + return defHttp.post({ + url: Api.AddPosition, + params, + }); +} + +export function updatePosition(params) { + return defHttp.post({ + url: Api.UpdatePosition, + params, + }); +} + +export function addDept(params) { + return defHttp.post({ + url: Api.AddDept, + params, + }); +} +export function updateDept(params) { + return defHttp.post({ + url: Api.UpdateDept, + params, + }); +} +export function deleteDept(params) { + return defHttp.post({ + url: Api.DeleteDept, + params, + }); +} +export function addMenu(params) { + return defHttp.post({ + url: Api.AddMenu, + params, + }); +} +export function addButton(params) { + return defHttp.post({ + url: Api.AddButton, + params, + }); +} +export function editMenu(params) { + return defHttp.post({ + url: Api.EditMenu, + params, + }); +} +export function editButton(params) { + return defHttp.post({ + url: Api.EditButton, + params, + }); +} +export function deleteMenu(params) { + return defHttp.post({ + url: Api.DeleteMenu, + params, + }); +} +export function deleteButton(params) { + return defHttp.post({ + url: Api.DeleteButton, + params, + }); +} + +export function addRole(params) { + return defHttp.post({ + url: Api.AddRole, + params, + }); +} +export function updateRole(params) { + return defHttp.post({ + url: Api.UpdateRole, + params, + }); +} +export function deleteRole(params) { + return defHttp.post({ + url: Api.DeleteRole, + params, + }); +} +export function assignModule(params) { + return defHttp.post({ + url: Api.AssignModule, + params, + }); +} + +export const getMenuDetail = (params?: MenuParams) => defHttp.get({ url: Api.MenuDetail, params }); +export const getAllModuleDetail = () => defHttp.get({ url: Api.AllModuleDetail }); + +export const getMenuList = (params?: MenuParams) => + defHttp.get({ url: Api.MenuList, params }); + +export const getButtonList = (params?: MenuParams) => + defHttp.get({ url: Api.ButtonList, params }); + +export const getRoleListByPage = (params?: RolePageParams) => + defHttp.get({ url: Api.RolePageList, params }); + +export const getAllRoleList = (params?: RoleParams) => + defHttp.get({ url: Api.GetAllRoleList, params }); + +export const setRoleStatus = (id: number, status: string) => + defHttp.post({ url: Api.setRoleStatus, params: { id, status } }); + +export const isAccountExist = (account: string) => + defHttp.post({ url: Api.IsAccountExist, params: { account } }, { errorMessageMode: 'none' }); + +export const getLoadPositionByOrg = (params?: PositionByOrgParams) => + defHttp.get({ url: Api.LoadPositionByOrg, params }); + +export const getLoadDataBaseLinkTree = () => defHttp.get({ url: Api.LoadDataBaseLinkTree }); + +export const getPosInfo = (params) => defHttp.get({ url: Api.GetPosInfo, params }); + +export const getUserRoles = (params) => defHttp.get({ url: Api.GetUserRoles, params }); + +export const getUserOrgs = (params) => defHttp.get({ url: Api.GetUserOrgs, params }); + +export const getReportList = (params: ReportParams) => + defHttp.get({ url: Api.ReportList, params }); + +export const getStatisticalList = (params: ReportParams) => + defHttp.get({ url: Api.StatisticalList, params }); + +export const exportStatisticalList = (params: ReportParams) => { + return defHttp.post({ + url: Api.StatisticalListExport, + params, + }); +}; + +export const getNoticeList = (params?: Object) => + defHttp.get({ url: Api.NoticeList, params }); + +export function addNotice(params) { + return defHttp.post({ + url: Api.AddNotice, + params, + }); +} + +export function updateNotice(params) { + return defHttp.post({ + url: Api.UpdateNotice, + params, + }); +} + +export function deleteNotice(params) { + return defHttp.post({ + url: Api.DeleteNotice, + params, + }); +} + +export function getNoticeDetail(params) { + return defHttp.get({ + url: Api.LoadNoticeDetail, + params, + }); +} + +export function getCaseInfoList(params) { + return defHttp.get({ + url: Api.ReportList, + params, + }); +} + +export const getUserList = (params: UserListParams) => + defHttp.get({ url: Api.UserList, params }); + +export const getSpecialData = () => defHttp.get({ url: Api.GetSpecialData }); +const loadCaseInfoTuBanListUrlObj = { + "违法用地": '/api/DroneCaseInfoSingle/LoadCaseInfoTuBanList', + "非法采矿": '', + "耕地非粮化": '/api/DroneCaseInfoFLH/LoadCaseInfoTuBanList', + "重点问题": '/api/DroneCaseInfoZdwt1/LoadCaseInfoTuBanListTotal', + "巡察审计": '/api/DroneCaseInfoXcsj/LoadCaseInfoTuBanList', + "生态保护红线": '/api/DroneCaseInfoSTHX/LoadCaseInfoTuBanList', + "生态修复": '/api/DroneCaseInfoSTXF/LoadCaseInfoTuBanList', +} +export function homePageLoadCaseInfoTuBanList(type,params) { + return defHttp.get({ + url: loadCaseInfoTuBanListUrlObj[type], + params, + }); +} +export function loadCaseInfoTuBanList(params) { + return defHttp.get({ + url: Api.LoadCaseInfoTuBanList, + params, + }); +} +export function loadCaseInfoIllegalList(params) { + return defHttp.get({ + url: Api.LoadCaseInfoIllegalList, + params, + }); +} +export const getCaseOffence = (params: ReportParams) => + defHttp.get({ url: Api.CaseOffence, params }); + +export const getLoadCaseInfoListOffence = (params: ReportParams) => + defHttp.get({ url: Api.LoadCaseInfoListOffence, params }); + +export function dealIllegalCaseInfo(params) { + return defHttp.post({ + url: Api.DealIllegalCaseInfo, + params, + }); +} +export function LoadCaseInfoListForUpdate(params) { + return defHttp.get({ + url: Api.LoadCaseInfoListForUpdate, + params, + }); +} +export function LoadCaseInfoById(params: { id: string }) { + return defHttp.get({ + url: Api.LoadCaseInfoById, + params, + }); +} +export function UpdateCaseInfo(data,shppath='') { + return defHttp.post({ + url: `${Api.UpdateCaseInfo}?shppath=${shppath}`, + data, + }); +} +export function LoadCaseHistoryInfoList(params: { key: string }) { + return defHttp.get({ + url: Api.LoadCaseHistoryInfoList, + params, + }); +} + +// 云查询图层 +// geo服务增加 +export const ShpGeoLayerAdd = (params, timeout = 0) => + defHttp.post({ url: Api.ShpGeoLayerAdd, params, timeout }); +// geo列表 +export const ShpGeoLayerLoadPage = (params) => + defHttp.get({ url: Api.ShpGeoLayerLoadPage, params }); +// geo获取 +export const ShpGeoLayerGet = (params) => + defHttp.get({ url: Api.ShpGeoLayerGet, params }); +// geo更新 +export const ShpGeoLayerUpdateLayer = (params) => + defHttp.post({ url: Api.ShpGeoLayerUpdateLayer, params }); +// geo删除 +export const ShpGeoLayerDelete = (params) => + defHttp.post({ url: Api.ShpGeoLayerDelete + '/' + params.id }); +// geo解析shp文件 +export const ShpGeoLayerParseShpInfo = (params) => + defHttp.post({ url: Api.ShpGeoLayerParseShpInfo + "?srid=" + params.srid + "&tableName=" + params.tableName + "&zipFilePath=" + params.zipFilePath }); +// 获取地图中心点 +export const getGeomData = (params) => + defHttp.get({ url: Api.getGeomData + "?tableName=" + params.dataTable }); +// 通过表名和id获取该条数据 +export const getDataTableRecord = (params) => + defHttp.get({ url: Api.getDataTableRecord + "?dataTable=" + params.dataTable + "&id=" + params.id }); + +// 影像管理 +// 更新tiff影像 +export const GeoTiffManagerUpdateGeoTiff = () => + defHttp.post({ url: Api.GeoTiffManagerUpdateGeoTiff }); +// 影像列表 +export const GeoTiffManagerLoadPage = (params) => + defHttp.get({ url: Api.GeoTiffManagerLoadPage, params }); +// 影像单个获取 +export const GeoTiffManagerGet = (params) => + defHttp.get({ url: Api.GeoTiffManagerGet, params }); +// 删除tiff影像 +export const GeoTiffManagerDeleteTifStore = (params) => + defHttp.post({ url: Api.DeleteTifStore + '?stores=' + params.stores }); +// 删除tiff影像 +export const GeoTiffManagerUpdateLayerGroupThumb = ((params) => { + if (params.bbox) { + return defHttp.post({ url: Api.UpdateLayerGroupThumb + '?layerGroups=' + params.layerGroups + "&num=" + params.num + "&width=" + params.width + "&height=" + params.height + "&bbox=" + params.bbox }); + } else { + return defHttp.post({ url: Api.UpdateLayerGroupThumb + '?layerGroups=' + params.layerGroups + "&num=" + params.num + "&width=" + params.width + "&height=" + params.height }); + } +}); + +// 成果管理-航飞图片 +// 添加成果 +export const AchievementManageAddImageexif = (params) => + defHttp.post({ url: Api.AchievementManageAddImageexif, params }); +// 案件判读 +export const AchievementManageIntactById = (params) => + defHttp.post({ url: Api.AchievementManageIntactById, params }); +// 添加任务 +export const AchievementManageAddTask = (params) => + defHttp.post({ url: Api.AchievementManageAddTask, params }); +// 任务查询 +export const AchievementManageListTask = (params) => + defHttp.get({ url: Api.AchievementManageListTask, params }); +// 任务查询个体 +export const AchievementManageListDroneShpImageexif = (params) => + defHttp.get({ url: Api.AchievementManageListDroneShpImageexif, params }); +// 成果管理-图层样式 +// 添加 +export const GeoStyleAdd = (params) => + defHttp.post({ url: Api.GeoStyleAdd, params }); +// 遍历 +export const GeoStylePage = (params) => + defHttp.get({ url: Api.GeoStylePage, params }); +// 非法采矿-统计列表 +export const CaseOffenceMinerals = (params: ReportParams) => + defHttp.get({ url: Api.CaseOffenceMinerals, params }); +// 非法采矿-统计列表New +export const CaseOffenceMineralsNew = (params: ReportParams) => + defHttp.get({ url: Api.CaseOffenceMineralsNew, params }); \ No newline at end of file diff --git a/src/api/demo/version.ts b/src/api/demo/version.ts new file mode 100644 index 0000000..ee81153 --- /dev/null +++ b/src/api/demo/version.ts @@ -0,0 +1,29 @@ +import { responsesmodel } from './model/queryModal'; +import { defHttp } from '@/utils/http/axios'; + +enum Api { + Get_GetUpdateFiles = '/api/SysAppFiles/GetUpdateFiles', + Post_AddAppFiles = '/api/SysAppFiles/AddAppFiles', + Get_DownLoadAppFile = '/api/SysAppFiles/DownLoadAppFile', +} + +export function fun_GetUpdateFiles(params) { + return defHttp.get({ + url: Api.Get_GetUpdateFiles, + params, + }); +} + +export function fun_AddAppFiles(params) { + return defHttp.post({ + url: Api.Post_AddAppFiles, + params, + }); +} + +export function fun_DownLoadAppFile(params) { + return defHttp.post({ + url: Api.Get_DownLoadAppFile, + params, + }); +} diff --git a/src/api/formdesign/index.ts b/src/api/formdesign/index.ts new file mode 100644 index 0000000..2e45e55 --- /dev/null +++ b/src/api/formdesign/index.ts @@ -0,0 +1,58 @@ +import { defHttp } from '@/utils/http/axios'; +import { + DemoOptionsItem, + selectParams, + AccountListGetResultModel, + AccountParams, + NoOptionsParam, + DeiginFormParam, + DataBaseSqlParam, + OutKeyParams, + ImportantDataBaseParam, +} from './model/index'; + +enum Api { + FORMSTYPES_LIST = '/api/SysDataItemDetail/Load', //字典 + GETDATABASETABLE_LIST = '/api/SysDatabaseLink/LoadDataBaseLinkTree', //获取数据库 + FORMS_LIST = '/api/FormScheme/LoadFormPage', //查询表单列表 + DATABASE_LIST = '/api/CodeTable/LoadCodeTablePage', //数据对象选择表 + GETIMPORTDATA_FORM = '/api/FormModule/GetTableList', // 查询导入数据表列表 + IMPORTDATABASE_TABLE = '/api/CodeTable/ImportTable?dbCode=', //导入数据表 + OUTKEY_LIST = '/api/CodeTable/GetForms', //获取数据表 + GETBASE_LIST = '/api/FormScheme/GetForm', //获取列表详情 + ADDFORM_DATA = '/api/FormScheme/AddForm', //新增表单设计 + EDITFORM_DATA = '/api/FormScheme/UpdateForm?id=', //编辑表单设计 + ADDSql_DATA = '/api/FormScheme/GetDataColName?dbCode=', // 添加编辑SQL +} +/** + * @description: Get sample options value + */ +export const getFormsTypeList = (params?: selectParams) => + defHttp.get({ url: Api.FORMSTYPES_LIST, params }); + +export const getFormGroupList = (params: AccountParams) => + defHttp.get({ url: Api.FORMS_LIST, params }); +export const getDataBaseTableList = (params: AccountParams) => + defHttp.get({ url: Api.DATABASE_LIST, params }); +export const getOutKeyList = (params: OutKeyParams) => + defHttp.get({ url: Api.OUTKEY_LIST, params }); +export const getBaseConfigList = (params: selectParams) => + defHttp.get({ url: Api.GETBASE_LIST, params }); +export const addFormDesignData = (params: DeiginFormParam) => + defHttp.post({ url: Api.ADDFORM_DATA, params }); +export const editFormDesignData = (params: DeiginFormParam) => + defHttp.post({ url: Api.EDITFORM_DATA + params.info.id, params }); +export const addFormSqlData = (params: DataBaseSqlParam) => + defHttp.post({ + url: Api.ADDSql_DATA + params.dbCode + '&sql=' + params.sql, + params, + }); +export const getImportBaseTableList = (params: NoOptionsParam) => + defHttp.get({ url: Api.GETIMPORTDATA_FORM, params }); +export const importDataBaseTable = (params: ImportantDataBaseParam) => + defHttp.post({ + url: Api.IMPORTDATABASE_TABLE + params.dbCode, + params, + }); +export const getDataBaseCodeList = (params: {}) => + defHttp.get({ url: Api.GETDATABASETABLE_LIST, params }); diff --git a/src/api/formdesign/model/index.ts b/src/api/formdesign/model/index.ts new file mode 100644 index 0000000..230204d --- /dev/null +++ b/src/api/formdesign/model/index.ts @@ -0,0 +1,56 @@ +import { BasicPageParams, BasicFetchResult } from '@/api/model/baseModel'; + +export interface DemoOptionsItem { + name: string; + id: string; +} + +export interface NoOptionsParam { + id: string; + info: any; + scheme: any; + dbCode: string; + sql: string; +} +export interface DeiginFormParam { + info: any; + scheme: any; +} +export interface DataBaseSqlParam { + dbCode: any; + sql: any; +} +export interface selectParams { + id: any; +} +export interface OutKeyParams { + tableNames: any; + dbCode: any; +} +export interface ImportantDataBaseParam { + tableList: any; + dbCode: any; +} + +export type AccountParams = BasicPageParams & { + account?: string; + nickname?: string; + [key: string]: any; +}; + +export interface AccountListItem { + id: string; + orderNo: string; + createTime: string; + status: number; + icon: string; + component: string; + permission: string; + scheme: any; +} +/** + * @description: Request list return value + */ +export type DemoOptionsGetResultModel = BasicFetchResult; + +export type AccountListGetResultModel = BasicFetchResult; diff --git a/src/api/formrender/index.ts b/src/api/formrender/index.ts new file mode 100644 index 0000000..b82f623 --- /dev/null +++ b/src/api/formrender/index.ts @@ -0,0 +1,69 @@ +import { defHttp } from '@/utils/http/axios'; +import { + AccountListGetResultModel, + AccountParams, + SaveFormsParams, + DeleteFormsParams, + getFormsParams, +} from './model/index'; + +enum Api { + GETDESIGNDATA = '/api/FormModule/GetEntityByCode', //获取设计数据 + GETFORMPAGEDATA = '/api/FormScheme/GetFormDataPage?id=', //获取表单分页数据 + SAVEFORMDATA = '/api/FormScheme/SaveForm', //新增编辑自定义表单 + DELFORMSDATA = '/api/FormScheme/DeleteFormData?id=', //删除表单数据 + GETFORMSDATADETAIL = '/api/FormScheme/GetFormData', //表单数据详情 + getFormData = '/api/FormScheme/GetFormData', //获取单行数据 + exportForm = '/api/FormModule/Export?id=', //导出 + DownloadTemplate = '/api/FormScheme/DownTemplateFile?id=', //下载模板 + UploadFile = '/api/Files/Upload', //上传文件 + UploadData = '/api/FormScheme/ImportExcel', //导入 +} + +/** + * @description: Get sample options value + */ +export const getFormsDesignData = (params: AccountParams) => + defHttp.get({ url: Api.GETDESIGNDATA, params }); +export const getFormsPageData = (params: AccountParams) => + defHttp.post({ + url: Api.GETFORMPAGEDATA + params.id + '&mid=' + params.mid, + params, + }); +export const saveFormsData = (params: SaveFormsParams) => + defHttp.post({ url: Api.SAVEFORMDATA, params }); +export const delFormsData = (params: DeleteFormsParams) => + defHttp.post({ + url: Api.DELFORMSDATA + params.id + '&key=' + params.key + '&keyValue=' + params.keyValue, + params, + }); +export const getFormsDataDetail = (params: DeleteFormsParams) => + defHttp.get({ url: Api.GETFORMSDATADETAIL, params }); +export const getFormData = (params: getFormsParams) => { + return defHttp.get({ + url: `${Api.getFormData}?id=${params.id}&key=${params.key}&keyValue=${params.keyValue}`, + }); +}; +export const exportForm = (params: AccountParams) => + defHttp.post({ + url: Api.exportForm + params.id + '&mid=' + params.mid + '&code=' + params.code, + responseType: 'blob', + params, + }); +export const DownloadTemplate = (id: string) => + defHttp.get({ + url: Api.DownloadTemplate + id, + responseType: 'blob', + }) +export const uploadFile = (params) => + defHttp.post({ + url: Api.UploadFile, + params, + headers: { + 'Content-type': 'multipart/form-data', + }, + }) +export const uploadData = (params) => + defHttp.post({ + url: `${Api.UploadData}?id=${params.id}&pkey=${params.pkey}&path=${params.path}`, + }) diff --git a/src/api/formrender/model/index.ts b/src/api/formrender/model/index.ts new file mode 100644 index 0000000..458eb09 --- /dev/null +++ b/src/api/formrender/model/index.ts @@ -0,0 +1,45 @@ +import { BasicFetchResult } from '@/api/model/baseModel'; + +export interface AccountListItem { + databaseLinkId: string; + dbName: string; + dbAlias: string; + dbType: number; + serverAddress: string; + dbConnection: string; + description: string; + scheme: string; + formScheme: string; + id: string; +} +/** + * @description: Request list return value + */ +export interface AccountParams { + id?: string; + keyword?: string; + page?: string; + limit?: string; + code?: any; + rows?: string; + mid?: string; +} +export interface SaveFormsParams { + schemeId?: string; + isUpdate?: any; + data?: any; + pkey?: string; + pkeyValue?: any; +} +export interface DeleteFormsParams { + id?: string; + key?: string; + keyValue?: any; +} +export interface getFormsParams { + id?: string; + key?: string; + keyValue?: any; +} + +export type AccountListGetResultModel = BasicFetchResult; diff --git a/src/api/model/baseModel.ts b/src/api/model/baseModel.ts new file mode 100644 index 0000000..6a811f2 --- /dev/null +++ b/src/api/model/baseModel.ts @@ -0,0 +1,12 @@ +export interface BasicPageParams { + page: number; + pageSize: number; +} + +export interface BasicFetchResult { + moduleIds?: any; + formScheme?: any; + elementIds?: any; + items: T[]; + total: number; +} diff --git a/src/api/nongjingquan/index.ts b/src/api/nongjingquan/index.ts new file mode 100644 index 0000000..3c13981 --- /dev/null +++ b/src/api/nongjingquan/index.ts @@ -0,0 +1,29 @@ +import { defHttp } from '@/utils/http/axios'; + +enum Api { + GetPageList = '/api/V_QLR/GetPageList', + GetModel = '/api/V_QLR/GetModel', + GetFiles = '/api/V_QLR/GetFiles', +} + +export function GetPageList(params) { + return defHttp.get({ + url: Api.GetPageList, + params, + timeout: 100000, + }); +} +export function GetModel(params) { + return defHttp.get({ + url: Api.GetModel, + params, + timeout: 100000, + }); +} +export function GetFiles(params) { + return defHttp.get({ + url: Api.GetFiles, + params, + timeout: 100000, + }); +} \ No newline at end of file diff --git a/src/api/permission/data.ts b/src/api/permission/data.ts new file mode 100644 index 0000000..8c2bc68 --- /dev/null +++ b/src/api/permission/data.ts @@ -0,0 +1,46 @@ +import { defHttp } from '@/utils/http/axios'; +import { AccountListGetResultModel, AccountListItem, AccountParams } from './model/index'; +enum Api { + tableList = '/api/BaseDataAuth/GetPageList/permission/data/page', + getDetailData = '/api/BaseDataAuth/GetEntity/permission/data', + addData = '/api/BaseDataAuth/AddForm/permission/data', + editData = '/api/BaseDataAuth/UpdateForm/permission/data/', + delData = '/api/BaseDataAuth/DeleteForm/permission/data/', + fieldOptions = '/api/BaseDataAuth/GetEntityByCode', +} +export const getTablesListData = (params?: AccountParams) => { + return defHttp.get({ + url: Api.tableList, + params, + }); +}; +export const getDetailsData = (params?: AccountParams) => { + return defHttp.get({ + url: Api.getDetailData, + params, + }); +}; +export const getFieldListData = (params?: AccountParams) => { + return defHttp.get({ + url: Api.fieldOptions, + params, + }); +}; +export const addTableData = (params?: AccountParams) => { + return defHttp.post({ + url: Api.addData, + params, + }); +}; +export const editTableData = (params?: AccountParams) => { + return defHttp.post({ + url: Api.editData + params.id, + params, + }); +}; +export const delTableData = (params?: AccountParams) => { + return defHttp.post({ + url: Api.delData + params.id, + params, + }); +}; diff --git a/src/api/permission/model/index.ts b/src/api/permission/model/index.ts new file mode 100644 index 0000000..f263e43 --- /dev/null +++ b/src/api/permission/model/index.ts @@ -0,0 +1,23 @@ +import { BasicFetchResult } from '@/api/model/baseModel'; + +export interface AccountListItem { + id: string; + name: string; + type: any; + code: any; + objectId: string; + objectType: string; + formula: any; +} +/** + * @description: Request list return value + */ +export interface AccountParams { + id: string; + key: string; + page: any; + limit: any; + code: any; +} + +export type AccountListGetResultModel = BasicFetchResult; diff --git a/src/api/sys/ThematicSetting.ts b/src/api/sys/ThematicSetting.ts new file mode 100644 index 0000000..7fd422f --- /dev/null +++ b/src/api/sys/ThematicSetting.ts @@ -0,0 +1,28 @@ +import { defHttp } from '@/utils/http/axios'; +enum Api{ + LoadPage = '/api/DroneCaseinfo/LoadCaseTopic', + GetTopicRelevance = '/api/DroneCaseinfo/LoadTopicRelevance', + GetCaseTypeList = '/api/SysDataItemDetail/Load', + GetRoleList = '/api/Roles/LoadPage', + AddTopicCaseType = '/api/DroneCaseinfo/AddTopicCaseType', + AddTopicRole = '/api/DroneCaseinfo/AddTopicRole' +} +export function LoadPage(params) { + return defHttp.get({ url: Api.LoadPage, params }); +} +export function GetTopicRelevance(params){ + return defHttp.get({ url: Api.GetTopicRelevance, params }); +} +export function GetCaseTypeList(params){ + params = {...params,code:'DRONE_CASE_TYPE'} + return defHttp.get({ url: Api.GetCaseTypeList, params }); +} +export function GetRoleList(params){ + return defHttp.get({ url: Api.GetRoleList, params }); +} +export function AddTopicCaseType(params){ + return defHttp.post({ url: Api.AddTopicCaseType, params }); +} +export function AddTopicRole(params){ + return defHttp.post({ url: Api.AddTopicRole, params }); +} \ No newline at end of file diff --git a/src/api/sys/WFDelegate.ts b/src/api/sys/WFDelegate.ts new file mode 100644 index 0000000..8da1e70 --- /dev/null +++ b/src/api/sys/WFDelegate.ts @@ -0,0 +1,15 @@ +// WFDelegate 流程模版基本信息 +import { defHttp } from '@/utils/http/axios'; +import { DetailParams } from './model/wfSchemeInfoModel'; + +enum Api { + // 创建流程 + LoadMyUserList = '/api/WFDelegate/LoadMyUserList', +} + +/** + * @description: getLoadMyUserList + */ +export function getLoadMyUserList(params?: DetailParams) { + return defHttp.get({ url: Api.LoadMyUserList, params }); +} diff --git a/src/api/sys/WFProcess.ts b/src/api/sys/WFProcess.ts new file mode 100644 index 0000000..7ae8b3c --- /dev/null +++ b/src/api/sys/WFProcess.ts @@ -0,0 +1,176 @@ +// WFProcess 流程模版基本信息 +import { defHttp } from '@/utils/http/axios'; +import { + CreateParams, + DeleteDraftParams, + RevokeAuditParams, + LoadNextAuditorsParams, +} from './model/WFProcessModel'; +import { MyUncompletedParams } from './model/WFTaskModel'; + +enum Api { + // 创建流程 + Create = '/api/WFProcess/Create', + // 保存草稿 + SaveDraft = '/api/WFProcess/SaveDraft', + // 我的流程 + LoadMyPage = '/api/WFProcess/LoadMyPage', + // 我的草稿 + LoadMyDraftPage = '/api/WFProcess/LoadMyDraftPage', + // 删除草稿 + DeleteDraft = '/api/WFProcess/DeleteDraft', + // 催办 + Urge = '/api/WFProcess/Urge', + // 撤销 + Revoke = '/api/WFProcess/Revoke', + // 审核撤销 + RevokeAudit = '/api/WFProcess/RevokeAudit', + // 获取流程图详情 + GetBPMN = '/api/WFProcess/GetBPMN', + // 重新创建流程 + CreateAgain = '/api/WFProcess/CreateAgain', + // 加签审核 + SignAudit = '/api/WFProcess/SignAudit', + // 流程审核 + Audit = '/api/WFProcess/Audit', + // 获取下一节点审核人 + LoadNextAuditors = '/api/WFProcess/LoadNextAuditors', + // 确认阅读 + ReadFlow = '/api/WFProcess/ReadFlow', + // 撤回 + Retract = '/api/WFProcess/Retract', + // 判读发起流程检查 + GetDraft = '/api/WFProcess/GetDraft', +} + +/** + * @description: getLoadMyPage + */ +export function getLoadNextAuditors(params?: LoadNextAuditorsParams) { + return defHttp.get({ url: Api.LoadNextAuditors, params }); +} +/** + * @description: 创建流程 + */ +export function create(params?: CreateParams) { + return defHttp.post({ + url: Api.Create, + params, + }); +} +/** + * @description: 重新创建流程 + */ +export function createAgain(params?: CreateParams) { + return defHttp.post({ + url: Api.CreateAgain, + params, + }); +} +/** + * @description: 加签审核 + */ +export function signAudit(id?: String, params?: CreateParams) { + return defHttp.post({ + url: Api.SignAudit + '?id=' + id, + params, + }); +} +/** + * @description: 流程审核 + */ +export function audit(id: String, params?: CreateParams) { + return defHttp.post({ + url: Api.Audit + '?id=' + id, + params, + }); +} + +/** + * @description: 流程撤回 + */ +export function retract(id: String, params?: any) { + return defHttp.post({ + url: Api.Retract + '?id=' + id, + params, + }); +} + +/** + * @description: 保存草稿 + */ +export function saveDraft(params?: CreateParams) { + return defHttp.post({ + url: Api.SaveDraft, + params, + }); +} +/** + * @description: getLoadMyPage + */ +export function getLoadMyPage(params?: MyUncompletedParams) { + return defHttp.get({ url: Api.LoadMyPage, params }); +} +/** + * @description: getLoadMyDraftPage + */ +export function getLoadMyDraftPage(params?: MyUncompletedParams) { + return defHttp.get({ url: Api.LoadMyDraftPage, params }); +} +/** + * @description: 删除草稿 + */ +export function deleteDraft(params: DeleteDraftParams) { + return defHttp.post({ + url: Api.DeleteDraft + '?id=' + params.id, + params, + }); +} +/** + * @description: 催办 + */ +export function urge(params: DeleteDraftParams) { + return defHttp.post({ + url: Api.Urge + '?id=' + params.id, + params, + }); +} +/** + * @description: 撤销 + */ +export function revoke(params: DeleteDraftParams) { + return defHttp.post({ + url: Api.Revoke + '?id=' + params.id, + params, + }); +} +/** + * @description: 审核撤销 + */ +export function revokeAudit(params: RevokeAuditParams) { + return defHttp.post({ + url: Api.RevokeAudit + '?id=' + params.id + '&taskId=' + params.taskId, + params, + }); +} +/** + * @description: getPBMN + */ +export function getBPMN(params: DeleteDraftParams) { + return defHttp.get({ url: Api.GetBPMN, params }); +} + +/** + * @description: 确认阅读 + */ +export function ReadFlow(id: string) { + return defHttp.post({ + url: Api.ReadFlow + '?id=' + id, + }); +} +export function GetDraft(params) { + return defHttp.get({ + url: Api.GetDraft, + params, + }); +} diff --git a/src/api/sys/WFSchemeInfo.ts b/src/api/sys/WFSchemeInfo.ts new file mode 100644 index 0000000..a5ea408 --- /dev/null +++ b/src/api/sys/WFSchemeInfo.ts @@ -0,0 +1,93 @@ +// WFSchemeInfo 流程模版基本信息 +import { defHttp } from '@/utils/http/axios'; +import { + SchemeListParams, + GetSchemeModel, + AddParams, + DeleteParams, + UpdateParams, + StateParams, + HistoryParams, + GetHistoryModel, + SchemeParams, + DetailParams, +} from './model/wfSchemeInfoModel'; + +enum Api { + // 流程模板基本信息 + LoadPage = '/api/WFSchemeInfo/LoadPage', + Add = '/api/WFSchemeInfo/Add', + Update = '/api/WFSchemeInfo/Update', + Delete = '/api/WFSchemeInfo/Delete', + UpDateState = '/api/WFSchemeInfo/UpDateState', + GetDetail = '/api/WFSchemeInfo/Get', + // 可用模板合集 + Load = '/api/WFSchemeInfo/Load', + // 流程模板详细信息 + LoadHistoryPage = '/api/WFScheme/LoadPage', + UpdateScheme = '/api/WFSchemeInfo/UpdateScheme', + // 获取某模板历史数据 + VerisonsLoad = '/api/WFScheme/Load', + // 获取自定义流程列表(流程发起页) + GetInfoList = '/api/WFSchemeInfo/GetInfoList', +} + +/** + * @description: getLoadPage 模板列表 + */ +export function getLoadPage(params?: SchemeListParams) { + return defHttp.get({ url: Api.LoadPage, params }); +} +export function getDetail(params?: DetailParams) { + return defHttp.get({ url: Api.GetDetail, params }); +} +/** + * @description: getLoad 可用模板列表 + */ +export function getLoad(params?: SchemeListParams) { + return defHttp.get({ url: Api.Load, params }); +} +/** + * @description: postAdd + */ +export function postAdd(params?: AddParams) { + return defHttp.post({ + url: Api.Add, + params, + }); +} + +export function update(params: UpdateParams) { + return defHttp.post({ + url: Api.Update + '?id=' + params.schemeinfo.id, + params, + }); +} + +export function del(params: DeleteParams) { + return defHttp.post({ url: Api.Delete + '?id=' + params.id }); +} + +export function updateState(params: StateParams) { + return defHttp.post({ url: Api.UpDateState + '?id=' + params.id + '&state=' + params.state }); +} + +export function getLoadHistoryPage(params?: HistoryParams) { + return defHttp.get({ url: Api.LoadHistoryPage, params }); +} +export function getVerisonsLoad(params?: HistoryParams) { + return defHttp.get({ url: Api.VerisonsLoad, params }); +} + +export function updateScheme(params: SchemeParams) { + return defHttp.post({ + url: Api.UpdateScheme + '?id=' + params.id + '&schemeId=' + params.schemeId, + }); +} + +/** + * @description: getInfoList 获取流程自定义列表 + */ +export function getInfoList(params) { + return defHttp.get({ url: Api.GetInfoList, params }); +} diff --git a/src/api/sys/WFTask.ts b/src/api/sys/WFTask.ts new file mode 100644 index 0000000..cbc1b1a --- /dev/null +++ b/src/api/sys/WFTask.ts @@ -0,0 +1,61 @@ +// WFTask +import { defHttp } from '@/utils/http/axios'; +import { MyUncompletedParams, TaskDetailParam, RetractParam } from './model/WFTaskModel'; + +enum Api { + // 我的待办 + LoadMyUncompletedPage = '/api/WFTask/LoadMyUncompletedPage', + // 我的已办 + LoadMyCompletedPage = '/api/WFTask/LoadMyCompletedPage', + // 我的传阅 + LoadMyReadPage = '/api/WFTask/LoadMyReadPage', + // 我的委托 + LoadMyDelegatePage = '/api/WFTask/LoadMyDelegatePage', + GetTaskDetail = '/api/WFTask/Get', + GetBPMNTask = '/api/WFTask/GetBPMN', + // 撤回 + GetRetractPageList = '/api/WFTask/GetRetractPageList', +} + +/** + * @description: getLoadMyUncompletedPage + */ +export function getLoadMyUncompletedPage(params?: MyUncompletedParams) { + return defHttp.get({ url: Api.LoadMyUncompletedPage, params }); +} +/** + * @description: getLoadMyCompletedPage + */ +export function getLoadMyCompletedPage(params?: MyUncompletedParams) { + return defHttp.get({ url: Api.LoadMyCompletedPage, params }); +} +/** + * @description: getLoadMyReadPage + */ +export function getLoadMyReadPage(params?: MyUncompletedParams) { + return defHttp.get({ url: Api.LoadMyReadPage, params }); +} +/** + * @description: getLoadMyDelegatePage + */ +export function getLoadMyDelegatePage(params?: MyUncompletedParams) { + return defHttp.get({ url: Api.LoadMyDelegatePage, params }); +} +/** + * @description: GetTaskDetail + */ +export function getTaskDetail(params?: TaskDetailParam) { + return defHttp.get({ url: Api.GetTaskDetail, params }); +} +/** + * @description: getBPMNTask + */ +export function getBPMNTask(params?: TaskDetailParam) { + return defHttp.get({ url: Api.GetBPMNTask, params }); +} +/** + * @description: getBPMNTask + */ +export function getRetractPageList(params?: RetractParam) { + return defHttp.get({ url: Api.GetRetractPageList, params }); +} diff --git a/src/api/sys/analysis.ts b/src/api/sys/analysis.ts new file mode 100644 index 0000000..b5d40c7 --- /dev/null +++ b/src/api/sys/analysis.ts @@ -0,0 +1,7 @@ +import { defHttp, } from '@/utils/http/axios'; +enum Api{ + uploadShp = '/geoserver/uploadFile', +} +export function uploadShp(params) { + return defHttp.post({ url: Api.uploadShp, data: params, headers: { 'Content-Type': 'multipart/form-data' }}); +} \ No newline at end of file diff --git a/src/api/sys/categories.ts b/src/api/sys/categories.ts new file mode 100644 index 0000000..284867c --- /dev/null +++ b/src/api/sys/categories.ts @@ -0,0 +1,37 @@ +import { defHttp } from '@/utils/http/axios'; +enum Api{ + getLeftTree = '/api/SysDataItem/Load', + getRightTable = '/api/SysDataItemDetail/Load', + addLeftItem = '/api/SysDataItem/Add', + addRightItem = '/api/SysDataItemDetail/Add', + delLeftItem = '/api/SysDataItem/Delete', + delRightItem = '/api/SysDataItemDetail/Delete', + editRightItem = '/api/SysDataItemDetail/Update', +} +export function getLeftTree() { + return defHttp.get({ url: Api.getLeftTree, }); +} +export function getDictionaryType() { + return defHttp.get({ url: Api.getLeftTree, }); +} +export function getDictionary(params){ + return defHttp.get({ url: Api.getRightTable, params }); +} +export function getRightTable(params) { + return defHttp.get({ url: Api.getRightTable, params }); +} +export function addLeftItem(params){ + return defHttp.post({ url: Api.addLeftItem, params }); +} +export function addRightItem(params){ + return defHttp.post({ url: Api.addRightItem + '?code=' + params.itemCode, params }); +} +export function delLeftItem(params){ + return defHttp.post({ url: Api.delLeftItem + '?id=' + params.id }); +} +export function delRightItem(params){ + return defHttp.post({ url: Api.delRightItem + '?id=' + params.id }); +} +export function editRightItem(params){ + return defHttp.post({ url: Api.editRightItem, params }); +} \ No newline at end of file diff --git a/src/api/sys/cloud.ts b/src/api/sys/cloud.ts new file mode 100644 index 0000000..5cb475e --- /dev/null +++ b/src/api/sys/cloud.ts @@ -0,0 +1,42 @@ +import { defHttp } from '@/utils/http/axios'; +enum Api{ + getLeftTree = '/api/SysDataItemDetail/Load', + addLeftItem = '/api/SysDataItemDetail/Add', + delLeftItem = '/api/SysDataItemDetail/Delete', + editLeftItem = '/api/SysDataItemDetail/Update', + LoadPage = '/api/DroneCloudQueryContent/LoadPage', + Get = '/api/DroneCloudQueryContent/Get', + Add = '/api/DroneCloudQueryContent/Add', + Update = '/api/DroneCloudQueryContent/Update', + Delete = '/api/DroneCloudQueryContent/Delete', +} + +// 分类 +export function getLeftTree(params) { + return defHttp.get({ url: Api.getLeftTree, params }); +} + +export function addLeftItem(params){ + return defHttp.post({ url: Api.addLeftItem + '?code=' + params.itemCode, params }); +} + +export function delLeftItem(params){ + return defHttp.post({ url: Api.delLeftItem + '?id=' + params.id }); +} + +// 云查询管理 +export function LoadPage(params) { + return defHttp.get({ url: Api.LoadPage, params }); +} +export function Get(params) { + return defHttp.get({ url: Api.Get, params }); +} +export function Add(params) { + return defHttp.post({ url: Api.Add, params }); +} +export function Update(params) { + return defHttp.post({ url: Api.Update, params }); +} +export function Delete(params) { + return defHttp.post({ url: Api.Delete + '?id=' + params.id , params }); +} \ No newline at end of file diff --git a/src/api/sys/flowPenal.ts b/src/api/sys/flowPenal.ts new file mode 100644 index 0000000..7ed7d3a --- /dev/null +++ b/src/api/sys/flowPenal.ts @@ -0,0 +1,26 @@ +import { defHttp } from '@/utils/http/axios'; +import { + TableListParams, + TableListModel, + TableFormsParams, + TableFormsModel, +} from './model/flowPenalModel'; + +enum Api { + GetTableList = '/api/FormModule/GetTableList', + GetTableForms = '/api/CodeTable/GetForms', + Update = '/api/SysDataItemDetail/Update', + Delete = '/api/SysDataItemDetail/Delete', +} +/** + * @description: getTableList 获取表 + */ +export function getTableList(params: TableListParams) { + return defHttp.get({ url: Api.GetTableList, params }); +} +/** + * @description: getTableForms 获取表的对象集合 + */ +export function getTableForms(params: TableFormsParams) { + return defHttp.get({ url: Api.GetTableForms, params }); +} diff --git a/src/api/sys/layerManagement.ts b/src/api/sys/layerManagement.ts new file mode 100644 index 0000000..8580207 --- /dev/null +++ b/src/api/sys/layerManagement.ts @@ -0,0 +1,176 @@ +import { defHttp } from '@/utils/http/axios'; +import { + AddLayerParams, + GetLayerListParams, + AddGeomParams, + GetGeomParams, + LoginResultModel, + GetUserInfoModel, + CalTubanAreaModel +} from './model/layerModel'; + +import { ErrorMessageMode } from '#/axios'; + +enum Api { + // Login = '/login', + // GetUserInfo = '/getUserInfo', + GetUserInfo = '/api/Check/GetUserProfile', + AddLayer = "/api/ShpLayerSource/PublishLayer", + DeleteLayer = "/api/ShpLayerSource/DeleteLayer", + GetLayerInfo = "/api/ShpLayerSource/Get", + UpdateLyaer = "/api/ShpLayerSource/UpdateLayer", + GetLayerList = "/api/ShpLayerSource/LoadPage", + AddGeom = "/api/ShpLayerSource/SaveShapeData", + GetGeom = "/api/ShpLayerSource/GetShapeData", + CalTubanArea = "/api/DroneCaseInfoSingle/CalTubanArea", + SplitAndCalTubanArea = "/api/DroneCaseInfoSingle/SplitAndCalTubanArea", + SplitTubanBackYuan = "/api/DroneCaseInfoSingle/SplitTubanBackYuan", + GetPermCode = '/getPermCode', + TestRetry = '/testRetry', + Login = '/api/Check/Login', + Logout = '/api/Check/Logout', + GetConfig = "/api/ShpLayerSource/LoadSettingConfig", + UpdateConfig = "/api/ShpLayerSource/UpdateSettingConfig", +} + +/** + * @description: getUserInfo + */ +export function getUserInfo() { + return defHttp.get({ url: Api.GetUserInfo }, { errorMessageMode: 'none' }); +} + +export function getPermCode() { + return defHttp.get({ url: Api.GetPermCode }); +} + +export function doLogout() { + return defHttp.post({ url: Api.Logout }); +} + +export function testRetry() { + return defHttp.get( + { url: Api.TestRetry }, + { + retryRequest: { + isOpenRetry: true, + count: 5, + waitTime: 1000, + }, + }, + ); +} + +export function addLayer1 () { + return defHttp.post({ url: Api.Logout }); +} + +export function addLayer(params: AddLayerParams) { + return defHttp.post( + { + url: Api.AddLayer, + params, + } + ); +} +export function getLayerInfo(params){ + return defHttp.get( + { + url: Api.GetLayerInfo, + params:params + }, + ); +} +export function updateLayer(params: AddLayerParams) { + return defHttp.post( + { + url: Api.UpdateLyaer, + params, + } + ); +} + +export function getLayerList(params:GetLayerListParams) { + return defHttp.get( + { + url: Api.GetLayerList, + params:params + }, + ); +} + +export function addGeom(params:AddGeomParams) { + return defHttp.post( + { + url: Api.AddGeom, + params, + } + ) +} + +export function getGeom(params:GetGeomParams) { + return defHttp.post( + { + url: Api.GetGeom, + params, + } + ) +} + +export function calTubanArea(params:CalTubanAreaModel){ + return defHttp.post( + { + url: Api.CalTubanArea, + params, + } + ) +} + +export function splitAndCalTubanArea(params:CalTubanAreaModel){ + return defHttp.post( + { + url: Api.SplitAndCalTubanArea, + params, + } + ) +} + + +export function splitTubanBackYuan(params:CalTubanAreaModel){ + return defHttp.post( + { + url: Api.SplitTubanBackYuan, + params, + } + ) +} + + +export function getConfig(params) { + return defHttp.get( + { + url: Api.GetConfig, + params, + } + ) +} + +export function updateConfig(params) { + return defHttp.post( + { + url: Api.UpdateConfig, + params, + } + ); +} + + + +export function deleteLayer(params) { + return defHttp.delete( + { + url: Api.DeleteLayer+"/"+params, + params, + } + ) +} \ No newline at end of file diff --git a/src/api/sys/leadreporting.ts b/src/api/sys/leadreporting.ts new file mode 100644 index 0000000..493c651 --- /dev/null +++ b/src/api/sys/leadreporting.ts @@ -0,0 +1,7 @@ +import { defHttp } from '@/utils/http/axios'; +enum Api{ + LoadPage = '/api/DroneClueReporting/QueryClueReporting', +} +export function getLoadPage(params) { + return defHttp.get({ url: Api.LoadPage, params }); +} \ No newline at end of file diff --git a/src/api/sys/menu.ts b/src/api/sys/menu.ts new file mode 100644 index 0000000..2425389 --- /dev/null +++ b/src/api/sys/menu.ts @@ -0,0 +1,14 @@ +import { defHttp } from '@/utils/http/axios'; +import { getMenuListResultModel } from './model/menuModel'; + +enum Api { + GetMenuList = '/api/Check/GetModulesTree', +} + +/** + * @description: Get user menu based on id + */ + +export const getMenuList = (params) => { + return defHttp.get({ url: Api.GetMenuList, params }); +}; diff --git a/src/api/sys/model/WFProcessModel.ts b/src/api/sys/model/WFProcessModel.ts new file mode 100644 index 0000000..5a941f9 --- /dev/null +++ b/src/api/sys/model/WFProcessModel.ts @@ -0,0 +1,44 @@ +/** + * @description: 创建流程参数 + */ +export interface CreateParams { + processId?: string | null; + schemeCode?: string; + title?: string; + userId?: string; + toUserId?: string; + nextUsers?: { + additionalProp1: string; + additionalProp2: string; + additionalProp3: string; + }; + des?: string; + code?: string; + name?: string; + stampImg?: string; + stampPassWord?: string; + nextId?: string; +} +/** + * @description: 删除草稿参数 + */ +export interface DeleteDraftParams { + id: string; +} +/** + * @description: 审核撤销参数 + */ +export interface RevokeAuditParams { + id: string; + taskId: string; +} +/** + * @description: 下一节点审核人参数 + */ +export interface LoadNextAuditorsParams { + code: string; + processId?: string | number; + nodeId: string; + operationCode: string; + userId: string; +} diff --git a/src/api/sys/model/WFTaskModel.ts b/src/api/sys/model/WFTaskModel.ts new file mode 100644 index 0000000..96c0a46 --- /dev/null +++ b/src/api/sys/model/WFTaskModel.ts @@ -0,0 +1,33 @@ +/** + * @description: 我的待办查询参数 + */ +export interface MyUncompletedParams { + keyWord: string; + page: number; + limit: number; + startDate: string; + endDate: string; +} +export interface TaskDetailParam { + id: string; +} + +// 可撤回列表参数 +export interface RetractParam { + keyWord: string; + page: number; + limit: number; + key: string; + StartDate: string; + EndDate: string; + Code: string; + Type: number; + CaseNo: string; + TypeId: string; + CaseName: string; + IsDrawback: number; + IsIllegal: number; + IsVerification: number; + CaseDescription: string; + category: string; +} diff --git a/src/api/sys/model/flowPenalModel.ts b/src/api/sys/model/flowPenalModel.ts new file mode 100644 index 0000000..5a4f622 --- /dev/null +++ b/src/api/sys/model/flowPenalModel.ts @@ -0,0 +1,29 @@ +/** + * @description: 表数据 + */ +export interface TableListModel { + name: string; + description: number; + dbObjectType: number; +} +/** + * @description: 获取数据库表 + */ +export interface TableListParams { + code: string; +} +/** + * @description: 表对象集合的参数 + */ +export interface TableFormsParams { + dbCode: string; + tableNames: string; +} + +/** + * @description: 表对象集合 + */ +export interface TableFormsModel { + db_codetable: object; + db_codecolumnsList: object; +} diff --git a/src/api/sys/model/layerModel.ts b/src/api/sys/model/layerModel.ts new file mode 100644 index 0000000..e141172 --- /dev/null +++ b/src/api/sys/model/layerModel.ts @@ -0,0 +1,80 @@ +/** + * @description: Login interface parameters + */ + export interface AddLayerParams { + relationTable:string; + name: string; + description: string; + srid: string; + vectorType:string; + style:string; + createTime:string +} + +export interface GetLayerListParams { + name:string; + page:number; + limit:number; + key:string; +} + +export interface AddGeomParams { + tableName:string; + guidFieldName:string; + geometryFieldName:string; + data:Array +} + +export interface GetGeomParams { + TableName:string; + FieldName:string; + FieldValue:Array, + page:number, + limit:number, + key:string | null, +} + +export interface CalTubanAreaModel{ + wktgeom: string | null; + gengdi: number | null, + nongyongdi: number | null, + jibennongtian: number | null, + shengtaihongxian: number | null, + gengdituban:string, + nongyongdituban:string | null, + jibennongtiantuban:string | null, + shengtaihongxiantuban:string | null, + remaintuban:string | null +} + + export interface RoleInfo { + roleName: string; + value: string; + } + + /** + * @description: Login interface return value + */ + export interface LoginResultModel { + userId: string | number; + token: string; + roles: RoleInfo[]; + } + + /** + * @description: Get user information return value + */ + export interface GetUserInfoModel { + roles: RoleInfo[]; + // 用户id + userId: string | number; + // 用户名 + username: string; + // 真实名字 + realName: string; + // 头像 + avatar: string; + // 介绍 + desc?: string; + } + \ No newline at end of file diff --git a/src/api/sys/model/menuModel.ts b/src/api/sys/model/menuModel.ts new file mode 100644 index 0000000..c2064a1 --- /dev/null +++ b/src/api/sys/model/menuModel.ts @@ -0,0 +1,17 @@ +import type { RouteMeta } from 'vue-router'; + +export interface RouteItem { + path: string; + component: any; + meta: RouteMeta; + name?: string; + alias?: string | string[]; + redirect?: string; + caseSensitive?: boolean; + children?: RouteItem[]; +} + +/** + * @description: Get menu return value + */ +export type getMenuListResultModel = RouteItem[]; diff --git a/src/api/sys/model/sysDataItemDetailModel.ts b/src/api/sys/model/sysDataItemDetailModel.ts new file mode 100644 index 0000000..43c3a97 --- /dev/null +++ b/src/api/sys/model/sysDataItemDetailModel.ts @@ -0,0 +1,61 @@ +/** + * @description: 字典明细接口区分参数 + */ +export interface CodeParams { + code: string; +} + +/** + * @description: 字典明细添加参数 + */ +export interface AddParams { + itemName?: string; + itemValue?: string; + sortCode?: number; + enabledMark?: number; + description?: string; +} + +/** + * @description: 字典明细更新参数 + */ +export interface UpdateParams { + itemDetailId?: string; + itemName?: string; + itemValue?: string; + sortCode?: number; + enabledMark?: number; + description?: string; +} + +/** + * @description: 分类明细删除参数 + */ +export interface DeleteParams { + id: string; +} + +/** + * @description: 获取分类明细返回值 + */ +export interface GetSysDataItemDetailItem { + itemDetailId: string; + itemId: string; + parentId: string; + itemCode: string; + itemName: string; + itemValue: string; + quickQuery: string; + simpleSpelling: string; + isDefault: string; + sortCode: number; + deleteMark: number; + enabledMark: number; + description: string; + createDate: string; + createUserName: string; + modifyDate: string; + modifyUserId: string; + modifyUserName: string; +} +export type RoleListGetResultModel = GetSysDataItemDetailItem[]; diff --git a/src/api/sys/model/uploadModel.ts b/src/api/sys/model/uploadModel.ts new file mode 100644 index 0000000..d770c64 --- /dev/null +++ b/src/api/sys/model/uploadModel.ts @@ -0,0 +1,5 @@ +export interface UploadApiResult { + message: string; + code: number; + url: string; +} diff --git a/src/api/sys/model/userModel.ts b/src/api/sys/model/userModel.ts new file mode 100644 index 0000000..3869219 --- /dev/null +++ b/src/api/sys/model/userModel.ts @@ -0,0 +1,38 @@ +/** + * @description: Login interface parameters + */ +export interface LoginParams { + username: string; + password: string; +} + +export interface RoleInfo { + roleName: string; + value: string; +} + +/** + * @description: Login interface return value + */ +export interface LoginResultModel { + userId: string | number; + token: string; + roles: RoleInfo[]; +} + +/** + * @description: Get user information return value + */ +export interface GetUserInfoModel { + roles: RoleInfo[]; + // 用户id + userId: string | number; + // 用户名 + username: string; + // 真实名字 + realName: string; + // 头像 + avatar: string; + // 介绍 + desc?: string; +} diff --git a/src/api/sys/model/wfSchemeInfoModel.ts b/src/api/sys/model/wfSchemeInfoModel.ts new file mode 100644 index 0000000..8198302 --- /dev/null +++ b/src/api/sys/model/wfSchemeInfoModel.ts @@ -0,0 +1,165 @@ +/** + * @description: 流程模板基本信息参数 + */ +export interface SchemeListParams { + key: string; + page: number; + limit: number; + category: string; + ids?: string; +} +/** + * @description: 获取流程模板详情参数 \获取数据库表 + */ +export interface DetailParams { + code?: string; +} + +/** + * @description: 流程模板添加参数 + */ +export interface AddParams { + schemeinfo: { + id: string; + code: string; + name: string; + category: string; + color: string; + icon: string; + schemeId: string; + enabledMark: 0; + mark: 0; + isInApp: 0; + authType: 0; + description: string; + type: 0; + createDate: string; + createUserId: string; + createUserName: string; + }; + schemeAuthList: [ + { + id: string; + schemeInfoId: string; + objName: string; + objId: string; + objType: 0; + }, + ]; + scheme: { + id: string; + schemeInfoId: string; + type: 0; + createDate: string; + createUserId: string; + createUserName: string; + content: string; + }; +} + +/** + * @description: 字典明细更新参数 + */ +export interface UpdateParams { + schemeinfo: { + id: string; + code: string; + name: string; + category: string; + color: string; + icon: string; + schemeId: string; + enabledMark: 0; + mark: 0; + isInApp: 0; + authType: 0; + description: string; + type: 0; + createDate: string; + createUserId: string; + createUserName: string; + }; + schemeAuthList: [ + { + id: string; + schemeInfoId: string; + objName: string; + objId: string; + objType: 0; + }, + ]; + scheme: { + id: string; + schemeInfoId: string; + type: 0; + createDate: string; + createUserId: string; + createUserName: string; + content: string; + }; +} + +/** + * @description: 分类明细删除参数 + */ +export interface DeleteParams { + id: string; +} + +export interface StateParams { + id: string; + state: number; +} + +/** + * @description: 获取分类明细返回值 + */ +export interface GetSchemeModel { + itemDetailId: string; + itemId: string; + parentId: string; + itemCode: string; + itemName: string; + itemValue: string; + quickQuery: string; + simpleSpelling: string; + isDefault: string; + sortCode: number; + deleteMark: number; + enabledMark: number; + description: string; + createDate: string; + createUserName: string; + modifyDate: string; + modifyUserId: string; + modifyUserName: string; +} + +/** + * @description: 历史记录查询参数 + */ +export interface HistoryParams { + key?: string; + page?: number; + limit?: number; + id?: string; +} +/** + * @description: 历史记录返回值 + */ +export interface GetHistoryModel { + id: string; + schemeInfoId: string; + type: number; + createDate: string; + createUserId: string; + createUserName: string; + content: string; +} +/** + * @description: 切换版本 + */ +export interface SchemeParams { + id: string; + schemeId: string; +} diff --git a/src/api/sys/specialcolumn.ts b/src/api/sys/specialcolumn.ts new file mode 100644 index 0000000..dce10f0 --- /dev/null +++ b/src/api/sys/specialcolumn.ts @@ -0,0 +1,68 @@ +import { defHttp } from '@/utils/http/axios'; +import { BasicFetchResult } from '@/api/model/baseModel'; + +// 常用返回消息 +export interface responses { + code: number; + columnHeaders: []; + count: number; + result: []; + msg: string; +} +export type responsesmodel = BasicFetchResult; + +enum Api { + // 分页获取列表数据 + LoadDataBaseInfo = '/api/Specialcolumn/LoadDataBaseInfo', + // 获取全部数据(不显示的除外) + GetDataColName = '/api/Specialcolumn/GetDataColName', + // 获取单个数据源 + GetEntityById = '/api/Specialcolumn/GetEntityById', + // 新增数据源 + AddOrUpdateForm = '/api/Specialcolumn/AddOrUpdateForm', + // 删除数据源 + DeleteEntity = '/api/Specialcolumn/DeleteEntity', + // 修改是否显示状态 + UpdateIsShow = '/api/Specialcolumn/UpdateIsShow', + } + +// 分页获取列表数据 +export function LoadDataBaseInfo(params) { + return defHttp.get({ + url: Api.LoadDataBaseInfo, + params, + }); +} +// 获取全部数据(不显示的除外) +export function GetDataColName(params) { + return defHttp.get({ + url: Api.GetDataColName, + params, + }); +} +// 获取单个数据源 +export function GetEntityById(params) { + return defHttp.get({ + url: Api.GetEntityById, + params, + }); +} +// 新增数据源 +export function AddOrUpdateForm(params) { + return defHttp.post({ + url: Api.AddOrUpdateForm + "?id=" + params.id, + params, + }); +} +// 删除数据源 +export function DeleteEntity(params) { + return defHttp.post({ + url: Api.DeleteEntity + "?id=" + params.id, + }); +} +// 修改是否显示状态 +export function UpdateIsShow(params) { + return defHttp.post({ + url: Api.UpdateIsShow + "?id=" + params.id + "&isshow=" + params.isshow, + }); +} diff --git a/src/api/sys/sysDataItemDetail.ts b/src/api/sys/sysDataItemDetail.ts new file mode 100644 index 0000000..05d86e9 --- /dev/null +++ b/src/api/sys/sysDataItemDetail.ts @@ -0,0 +1,50 @@ +// sysDataItemDetail 字典明细接口api +import { defHttp } from '@/utils/http/axios'; +import { + CodeParams, + AddParams, + UpdateParams, + DeleteParams, + GetSysDataItemDetailModel, +} from './model/sysDataItemDetailModel'; +enum Api { + Load = '/api/SysDataItemDetail/Load', + Add = '/api/SysDataItemDetail/Add', + Update = '/api/SysDataItemDetail/Update', + Delete = '/api/SysDataItemDetail/Delete', +} + +/** + * @description: postAdd + */ +export function postAdd(code: string, params?: AddParams) { + return defHttp.post({ + url: Api.Add + '?code=' + code, + params, + }); +} + +/** + * @description: getLoad + */ +export function getLoad(params: CodeParams) { + return defHttp.get({ url: Api.Load, params }); +} + +export function update(params?: UpdateParams) { + console.log(params); + return defHttp.post({ + url: Api.Update, + params, + }); +} + +export function del(params: DeleteParams) { + return defHttp.post({ url: Api.Delete + '?id=' + params.id }); +} +export function getLoadCaseType() { + const params = { + code: 'DRONE_CASE_TYPE', + }; + return defHttp.get({ url: Api.Load, params }); +} diff --git a/src/api/sys/technologicalprocess.ts b/src/api/sys/technologicalprocess.ts new file mode 100644 index 0000000..ff73f6f --- /dev/null +++ b/src/api/sys/technologicalprocess.ts @@ -0,0 +1,27 @@ +import { defHttp } from '@/utils/http/axios'; +enum Api{ + LoadPage = '/api/DroneCaseinfo/LoadDroneFlowInstance', + AddOrUpdateDroneFlowInstance = '/api/DroneCaseinfo/AddOrUpdateDroneFlowInstance', + DeleteDroneFlowInstance = '/api/DroneCaseinfo/DeleteDroneFlowInstance', + GetRolesList = '/api/Roles/LoadPage', + GetBindRolesList = '/api/DroneCaseinfo/LoadDroneFlowRoleBindData', + BindRolesList = '/api/DroneCaseinfo/DroneFlowInstanceBindRole' +} +export function AddOrUpdateDroneFlowInstance(params) { + return defHttp.post({ url: Api.AddOrUpdateDroneFlowInstance, params }); +} +export function LoadPage(params) { + return defHttp.get({ url: Api.LoadPage, params }); +} +export function DeleteDroneFlowInstance(params) { + return defHttp.post({ url: Api.DeleteDroneFlowInstance, params }); +} +export function GetRolesList(params) { + return defHttp.get({ url: Api.GetRolesList, params }); +} +export function GetBindRolesList(params) { + return defHttp.get({ url: Api.GetBindRolesList, params }); +} +export function BindRolesList(params) { + return defHttp.post({ url: Api.BindRolesList, params }); +} \ No newline at end of file diff --git a/src/api/sys/upload.ts b/src/api/sys/upload.ts new file mode 100644 index 0000000..724db76 --- /dev/null +++ b/src/api/sys/upload.ts @@ -0,0 +1,35 @@ +import { UploadApiResult } from './model/uploadModel'; +import { defHttp } from '@/utils/http/axios'; +import { UploadFileParams } from '#/axios'; +import { useGlobSetting } from '@/hooks/setting'; +import { AxiosProgressEvent } from 'axios'; + +const { uploadUrl } = useGlobSetting(); + +const uploadFileUrl = uploadUrl + '/api/Platform/Upload'; +/** + * @description: Upload interface + */ +export function uploadApi( + params: UploadFileParams, + onUploadProgress: (progressEvent: AxiosProgressEvent) => void, +) { + return defHttp.uploadFile( + { + url: uploadFileUrl, + onUploadProgress, + }, + params, + ); +} + + +export function fileUploadApi(params: UploadFileParams,url:string,onUploadProgress: (progressEvent: AxiosProgressEvent) => void,) { + return defHttp.uploadFile( + { + url: url, + onUploadProgress, + }, + params, + ); +} diff --git a/src/api/sys/user.ts b/src/api/sys/user.ts new file mode 100644 index 0000000..c0902b7 --- /dev/null +++ b/src/api/sys/user.ts @@ -0,0 +1,68 @@ +import { defHttp } from '@/utils/http/axios'; +import { LoginParams, LoginResultModel, GetUserInfoModel } from './model/userModel'; + +import { ErrorMessageMode } from '#/axios'; + +enum Api { + // Login = '/login', + // GetUserInfo = '/getUserInfo', + GetUserInfo = '/api/Check/GetUserProfile', + GetPermCode = '/getPermCode', + TestRetry = '/testRetry', + Login = '/api/Check/Login', + Logout = '/api/Check/Logout', +} + +/** + * @description: user login api + */ +export function loginApi(params: LoginParams, mode: ErrorMessageMode = 'modal') { + console.log( + defHttp.post( + { + url: Api.Login, + params, + }, + { + errorMessageMode: mode, + }, + ), + ); + return defHttp.post( + { + url: Api.Login, + params, + }, + { + errorMessageMode: mode, + }, + ); +} + +/** + * @description: getUserInfo + */ +export function getUserInfo() { + return defHttp.get({ url: Api.GetUserInfo }, { errorMessageMode: 'none' }); +} + +export function getPermCode() { + return defHttp.get({ url: Api.GetPermCode }); +} + +export function doLogout() { + return defHttp.post({ url: Api.Logout }); +} + +export function testRetry() { + return defHttp.get( + { url: Api.TestRetry }, + { + retryRequest: { + isOpenRetry: true, + count: 5, + waitTime: 1000, + }, + }, + ); +} diff --git a/src/api/tiankongdi/index.ts b/src/api/tiankongdi/index.ts new file mode 100644 index 0000000..37d0ed9 --- /dev/null +++ b/src/api/tiankongdi/index.ts @@ -0,0 +1,206 @@ +// WFProcess 流程模版基本信息 +import { defHttp } from '@/utils/http/axios'; +import { + taskCountParams, + caseInfoParams, + countModel, + taskInfoParams, + addCaseFavoriteParams, + updateCaseInfoParams, +} from './model/index'; + +enum Api { + // 获取待办任务统计数据 + LoadTaskCount = '/api/DroneCaseInfoSingle/LoadTaskCount', + // 获取图斑信息统计数据 + LoadDroneCaseInfoCount = '/api/DroneCaseInfoSingle/LoadDroneCaseInfoCount', + // 分页获取图斑信息列表 + LoadDroneCaseInfoDetail = '/api/DroneCaseInfoSingle/LoadTasklList', + // 分页获取任务信息列表 + LoadTaskDetailList = '/api/DroneCaseInfoSingle/LoadTaskDetailList', + // 收藏图斑 + AddCaseFavorite = '/api/DroneCaseInfoSingle/AddCaseFavorite', + // 获取收藏图斑列表 + FavoriteCaseList = '/api/DroneCaseinfo/FavoriteCaseList', + DeleteFavoriteCase = '/api/DroneCaseInfoSingle/DeleteFavoriteCase', + // 获取图斑详情 + GetCaseInfoById = '/api/DroneCaseInfoSingle/GetCaseInfoById', + // 更新图斑行政区划 + UpdateDroneCaseInfo = '/api/DroneCaseInfoSingle/UpdateDroneCaseInfo', + // 督办流程 + Supervise = '/api/WFProcess/Supervise', + // 获取部门父级 + LoadParents = '/api/Orgs/LoadParents', + // 审核列表收藏 + AddtaskFavorite = '/api/DroneCaseInfoSingle/AddtaskFavorite', + // 审核列表删除收藏 + DeleteTaskCase = '/api/DroneCaseInfoSingle/DeleteTaskCase', + // 获取当前账号可以看见的乡镇 + loadStreet = '/api/DroneCaseInfoSingle/loadStreet', + // 违法处理,待办任务列表 + LoadTaskIllegalDetailList = '/api/DroneCaseInfoSingle/LoadTaskIllegalDetailList', + // 分割图斑 + SplitCase = '/api/DroneCaseInfoSingle/CaseSplit', + // 恢复还原 + RecoverCase = '/api/DroneCaseInfoSingle/CaseRecover', + // 获取图斑中心点 + GetPolygonCenter = '/api/DroneCaseInfoSingle/GetCenterPoints', + // 获取用户访问机构权限 + GetUserOrgs = '/api/Check/GetOrgs', + // 大屏下发图斑统计 + IssuedStatitical = '/api/DroneScreenDisplay/CaseOffenceXiaFa', + // 大屏核实新增统计 + VerifyStatitical = '/api/DroneScreenDisplay/CaseOffenceCheckAdd', + // 大屏整改剩余统计 + RectificationStatitical = '/api/DroneScreenDisplay/CaseOffenceModifyRemain', + // 获取案件图片坐标、方位角信息 + LoadCaseImgList = '/api/DroneCaseInfoSingle/LoadCaseImgList', + // 获取范围内影像服务信息 + GetIntersects = '/api/GeoTiffManager/GetIntersects', + // 获取网络环境 + GetNetWorkEev = '/api/DroneCloudQuery/IsPublic', + // 获取其他专题或历史图斑图片 + rebackzhuantipic = '/api/DroneCaseInfoSingle/rebackzhuantipic', + CopyImg = '/api/DroneCaseInfoSingle/CopyImg', + // 获取其他专题或历史图斑附件 + rebackzhuantifujian = '/api/DroneCaseInfoSingle/rebackzhuantifujian', + Copyfujian = '/api/DroneCaseInfoSingle/Copyfujian', +} + +/** + * @description: getCaseFlowLog + */ +export function getLoadTaskCount(params?: taskCountParams) { + return defHttp.get({ url: Api.LoadTaskCount, params }); +} +export function getLoadStreet() { + return defHttp.get({ url: Api.loadStreet }); +} + +/** + * @description: getCaseFlowLog + */ +export function getLoadDroneCaseInfoCount(params?: taskCountParams) { + return defHttp.get({ url: Api.LoadDroneCaseInfoCount, params }); +} + +/** + * @description: getCaseFlowLog + */ +export function getLoadDroneCaseInfoDetail(params?: caseInfoParams) { + return defHttp.get({ url: Api.LoadDroneCaseInfoDetail, params }); +} +/** + * @description: getCaseFlowLog + */ +export function getLoadTaskDetailList(params?: taskInfoParams) { + return defHttp.get({ url: Api.LoadTaskDetailList, params }); +} + +export function addCaseFavorite(params?: addCaseFavoriteParams) { + return defHttp.post({ url: Api.AddCaseFavorite, params }); +} +export function addTaskFavorite(params?: { taskId: string; favoriteUserId: string }) { + return defHttp.post({ url: Api.AddtaskFavorite, params }); +} +export function deleteFavoriteCase(params: string) { + return defHttp.post({ url: Api.DeleteFavoriteCase, data: params }); +} +export function deleteTaskCase(params: string) { + return defHttp.post({ url: Api.DeleteTaskCase, data: params }); +} + +export function getFavoriteCaseList(params?: { uid: string }) { + return defHttp.get({ url: Api.FavoriteCaseList, params }); +} +export function getCaseInfoById(params?: { id: string }) { + return defHttp.get({ url: Api.GetCaseInfoById, params }); +} +export const updateDroneCaseInfo = (params: updateCaseInfoParams) => + defHttp.post({ url: Api.UpdateDroneCaseInfo, params }); + +export const updateSupervise = (params: { id: string; supervise: number }) => + defHttp.post({ url: `${Api.Supervise}?id=${params.id}&supervise=${params.supervise}`, params }); + +export const getLoadParents = (params: { childId: Number }) => + defHttp.get({ url: `${Api.LoadParents}?childId=${params.childId}` }); + +export function getLoadTaskIllegalDetailList(params?: taskInfoParams) { + return defHttp.get({ url: Api.LoadTaskIllegalDetailList, params }); +} + +export function splitCase(params) { + return defHttp.post({ url: Api.SplitCase, data: params }); +} + +export function recoverCase(params) { + return defHttp.post({ url: Api.RecoverCase, data: params }); +} + +export function getPolygonCenter(params) { + return defHttp.get({ url: Api.GetPolygonCenter, params }); +} + +export function getUserOrgs(params) { + return defHttp.get({ url: Api.GetUserOrgs, params }); +} + +export function getIssuedStatitical(params) { + return defHttp.get({ + url: Api.IssuedStatitical, + params, + }); +} + +export function getVerifyStatitical(params) { + return defHttp.get({ + url: Api.VerifyStatitical, + params, + }); +} + +export function getRectificationStatitical(params) { + return defHttp.get({ + url: Api.RectificationStatitical, + params, + }); +} + +export function getLoadCaseImgList(params) { + return defHttp.get({ + url: Api.LoadCaseImgList, + params, + }); +} + +export function getIntersectTif(params) { + return defHttp.get({ url: Api.GetIntersects, params }); +} + +export function getNetworkType() { + return defHttp.get({ url: Api.GetNetWorkEev }); +} +export function rebackzhuantipic(params: { zhuanti; CaseId }) { + return defHttp.get({ + url: Api.rebackzhuantipic, + params, + }); +} +export function CopyImg(params: { caseid; images }) { + return defHttp.post({ + url: Api.CopyImg, + data: params, + }); +} +export function rebackzhuantifujian(params: { zhuanti; CaseId }) { + return defHttp.get({ + url: Api.rebackzhuantifujian, + params, + }); +} +export function Copyfujian(params: string[]) { + return defHttp.post({ + url: Api.Copyfujian, + data: params, + }); +} diff --git a/src/api/tiankongdi/model/index.ts b/src/api/tiankongdi/model/index.ts new file mode 100644 index 0000000..ec41f91 --- /dev/null +++ b/src/api/tiankongdi/model/index.ts @@ -0,0 +1,54 @@ +export interface taskCountParams { + year?: number; +} + +export interface taskInfoParams { + page?: number; + limit?: number; + level?: number; + areaid?: string; + geomid?: string; + year?: number; + is_build_complete?: number; +} + +export interface addCaseFavoriteParams { + id: string; + caseNo: string; + favoriteUserId: string; +} + +export interface caseInfoParams { + page?: number; + limit?: number; + level?: number; + areaid?: string; + year?: number; + geomid?: string; + countyid?: string; + streetid?: string; + is_illegal?: number; + weifaleixing?: number; + measure_name?: string; + is_build_complete?: number; + handle_status_id?: number; + key?: string; +} + +export interface countItem { + areaid: string; + areaname: string; + level: number; + count: number; +} +export type countModel = countItem[]; + +export interface updateCaseInfoParams { + id?: string; + countyid?: string; + countyname?: string; + streetid?: string; + streetname?: string; + communityid?: string; + communityname?: string; +} diff --git a/src/assets/icons/download-count.svg b/src/assets/icons/download-count.svg new file mode 100644 index 0000000..1c95195 --- /dev/null +++ b/src/assets/icons/download-count.svg @@ -0,0 +1 @@ +Asset 91 \ No newline at end of file diff --git a/src/assets/icons/dynamic-avatar-1.svg b/src/assets/icons/dynamic-avatar-1.svg new file mode 100644 index 0000000..e1553e5 --- /dev/null +++ b/src/assets/icons/dynamic-avatar-1.svg @@ -0,0 +1 @@ +Asset 15 \ No newline at end of file diff --git a/src/assets/icons/dynamic-avatar-2.svg b/src/assets/icons/dynamic-avatar-2.svg new file mode 100644 index 0000000..c4c1722 --- /dev/null +++ b/src/assets/icons/dynamic-avatar-2.svg @@ -0,0 +1 @@ +Asset 16 \ No newline at end of file diff --git a/src/assets/icons/dynamic-avatar-3.svg b/src/assets/icons/dynamic-avatar-3.svg new file mode 100644 index 0000000..81145f9 --- /dev/null +++ b/src/assets/icons/dynamic-avatar-3.svg @@ -0,0 +1 @@ +Asset 17 \ No newline at end of file diff --git a/src/assets/icons/dynamic-avatar-4.svg b/src/assets/icons/dynamic-avatar-4.svg new file mode 100644 index 0000000..e586ed4 --- /dev/null +++ b/src/assets/icons/dynamic-avatar-4.svg @@ -0,0 +1 @@ +Asset 120 \ No newline at end of file diff --git a/src/assets/icons/dynamic-avatar-5.svg b/src/assets/icons/dynamic-avatar-5.svg new file mode 100644 index 0000000..746e4b8 --- /dev/null +++ b/src/assets/icons/dynamic-avatar-5.svg @@ -0,0 +1 @@ +Asset 110 \ No newline at end of file diff --git a/src/assets/icons/dynamic-avatar-6.svg b/src/assets/icons/dynamic-avatar-6.svg new file mode 100644 index 0000000..b2432f2 --- /dev/null +++ b/src/assets/icons/dynamic-avatar-6.svg @@ -0,0 +1 @@ +Asset 100 \ No newline at end of file diff --git a/src/assets/icons/moon.svg b/src/assets/icons/moon.svg new file mode 100644 index 0000000..e6667f0 --- /dev/null +++ b/src/assets/icons/moon.svg @@ -0,0 +1,16 @@ + + + + + + + + + diff --git a/src/assets/icons/sun.svg b/src/assets/icons/sun.svg new file mode 100644 index 0000000..a3997cb --- /dev/null +++ b/src/assets/icons/sun.svg @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/assets/icons/test.svg b/src/assets/icons/test.svg new file mode 100644 index 0000000..244252d --- /dev/null +++ b/src/assets/icons/test.svg @@ -0,0 +1,21 @@ + + + + Icon1@3x + Created with Sketch. + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/icons/total-sales.svg b/src/assets/icons/total-sales.svg new file mode 100644 index 0000000..eff7964 --- /dev/null +++ b/src/assets/icons/total-sales.svg @@ -0,0 +1 @@ +Asset 500 \ No newline at end of file diff --git a/src/assets/icons/transaction.svg b/src/assets/icons/transaction.svg new file mode 100644 index 0000000..7ba9e2f --- /dev/null +++ b/src/assets/icons/transaction.svg @@ -0,0 +1 @@ +Asset 480% \ No newline at end of file diff --git a/src/assets/icons/visit-count.svg b/src/assets/icons/visit-count.svg new file mode 100644 index 0000000..ba2a306 --- /dev/null +++ b/src/assets/icons/visit-count.svg @@ -0,0 +1 @@ +Asset 510 \ No newline at end of file diff --git a/src/assets/images/demo.png b/src/assets/images/demo.png new file mode 100644 index 0000000..1a45c98 Binary files /dev/null and b/src/assets/images/demo.png differ diff --git a/src/assets/images/header.jpg b/src/assets/images/header.jpg new file mode 100644 index 0000000..e3906bd Binary files /dev/null and b/src/assets/images/header.jpg differ diff --git a/src/assets/images/icon_fly2.png b/src/assets/images/icon_fly2.png new file mode 100644 index 0000000..180449d Binary files /dev/null and b/src/assets/images/icon_fly2.png differ diff --git a/src/assets/svg/illustration.svg b/src/assets/svg/illustration.svg new file mode 100644 index 0000000..b45215b --- /dev/null +++ b/src/assets/svg/illustration.svg @@ -0,0 +1 @@ +Asset 336 \ No newline at end of file diff --git a/src/assets/svg/login-bg-dark.svg b/src/assets/svg/login-bg-dark.svg new file mode 100644 index 0000000..888da7a --- /dev/null +++ b/src/assets/svg/login-bg-dark.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/src/assets/svg/login-bg.svg b/src/assets/svg/login-bg.svg new file mode 100644 index 0000000..7b66baf --- /dev/null +++ b/src/assets/svg/login-bg.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/src/assets/svg/login-box-bg.svg b/src/assets/svg/login-box-bg.svg new file mode 100644 index 0000000..ee7dbdc --- /dev/null +++ b/src/assets/svg/login-box-bg.svg @@ -0,0 +1 @@ +responsive \ No newline at end of file diff --git a/src/assets/svg/net-error.svg b/src/assets/svg/net-error.svg new file mode 100644 index 0000000..81f2004 --- /dev/null +++ b/src/assets/svg/net-error.svg @@ -0,0 +1 @@ +personal settings \ No newline at end of file diff --git a/src/assets/svg/no-data.svg b/src/assets/svg/no-data.svg new file mode 100644 index 0000000..2b9f257 --- /dev/null +++ b/src/assets/svg/no-data.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/svg/preview/p-rotate.svg b/src/assets/svg/preview/p-rotate.svg new file mode 100644 index 0000000..5153a81 --- /dev/null +++ b/src/assets/svg/preview/p-rotate.svg @@ -0,0 +1 @@ + diff --git a/src/assets/svg/preview/resume.svg b/src/assets/svg/preview/resume.svg new file mode 100644 index 0000000..0e86c5f --- /dev/null +++ b/src/assets/svg/preview/resume.svg @@ -0,0 +1 @@ + diff --git a/src/assets/svg/preview/scale.svg b/src/assets/svg/preview/scale.svg new file mode 100644 index 0000000..1f7adae --- /dev/null +++ b/src/assets/svg/preview/scale.svg @@ -0,0 +1 @@ + diff --git a/src/assets/svg/preview/unrotate.svg b/src/assets/svg/preview/unrotate.svg new file mode 100644 index 0000000..e4708be --- /dev/null +++ b/src/assets/svg/preview/unrotate.svg @@ -0,0 +1 @@ + diff --git a/src/assets/svg/preview/unscale.svg b/src/assets/svg/preview/unscale.svg new file mode 100644 index 0000000..1359b34 --- /dev/null +++ b/src/assets/svg/preview/unscale.svg @@ -0,0 +1 @@ + diff --git a/src/components/Application/index.ts b/src/components/Application/index.ts new file mode 100644 index 0000000..e97d33e --- /dev/null +++ b/src/components/Application/index.ts @@ -0,0 +1,15 @@ +import { withInstall } from '@/utils'; + +import appLogo from './src/AppLogo.vue'; +import appProvider from './src/AppProvider.vue'; +import appSearch from './src/search/AppSearch.vue'; +import appLocalePicker from './src/AppLocalePicker.vue'; +import appDarkModeToggle from './src/AppDarkModeToggle.vue'; + +export { useAppProviderContext } from './src/useAppContext'; + +export const AppLogo = withInstall(appLogo); +export const AppProvider = withInstall(appProvider); +export const AppSearch = withInstall(appSearch); +export const AppLocalePicker = withInstall(appLocalePicker); +export const AppDarkModeToggle = withInstall(appDarkModeToggle); diff --git a/src/components/Application/src/AppDarkModeToggle.vue b/src/components/Application/src/AppDarkModeToggle.vue new file mode 100644 index 0000000..6b912f1 --- /dev/null +++ b/src/components/Application/src/AppDarkModeToggle.vue @@ -0,0 +1,78 @@ + + + diff --git a/src/components/Application/src/AppLocalePicker.vue b/src/components/Application/src/AppLocalePicker.vue new file mode 100644 index 0000000..f44a2f7 --- /dev/null +++ b/src/components/Application/src/AppLocalePicker.vue @@ -0,0 +1,76 @@ + + + + + diff --git a/src/components/Application/src/AppLogo.vue b/src/components/Application/src/AppLogo.vue new file mode 100644 index 0000000..16b012d --- /dev/null +++ b/src/components/Application/src/AppLogo.vue @@ -0,0 +1,100 @@ + + + + diff --git a/src/components/Application/src/AppProvider.vue b/src/components/Application/src/AppProvider.vue new file mode 100644 index 0000000..5481802 --- /dev/null +++ b/src/components/Application/src/AppProvider.vue @@ -0,0 +1,82 @@ + diff --git a/src/components/Application/src/search/AppSearch.vue b/src/components/Application/src/search/AppSearch.vue new file mode 100644 index 0000000..e017f42 --- /dev/null +++ b/src/components/Application/src/search/AppSearch.vue @@ -0,0 +1,33 @@ + diff --git a/src/components/Application/src/search/AppSearchFooter.vue b/src/components/Application/src/search/AppSearchFooter.vue new file mode 100644 index 0000000..7c92c7b --- /dev/null +++ b/src/components/Application/src/search/AppSearchFooter.vue @@ -0,0 +1,59 @@ + + + + diff --git a/src/components/Application/src/search/AppSearchKeyItem.vue b/src/components/Application/src/search/AppSearchKeyItem.vue new file mode 100644 index 0000000..08e3dbd --- /dev/null +++ b/src/components/Application/src/search/AppSearchKeyItem.vue @@ -0,0 +1,12 @@ + + diff --git a/src/components/Application/src/search/AppSearchModal.vue b/src/components/Application/src/search/AppSearchModal.vue new file mode 100644 index 0000000..76cc0c3 --- /dev/null +++ b/src/components/Application/src/search/AppSearchModal.vue @@ -0,0 +1,266 @@ + + + + diff --git a/src/components/Application/src/search/useMenuSearch.ts b/src/components/Application/src/search/useMenuSearch.ts new file mode 100644 index 0000000..5f29c2b --- /dev/null +++ b/src/components/Application/src/search/useMenuSearch.ts @@ -0,0 +1,167 @@ +import { type Menu } from '@/router/types'; +import { type AnyFunction } from '@vben/types'; +import { ref, onBeforeMount, unref, Ref, nextTick } from 'vue'; +import { getMenus } from '@/router/menus'; +import { cloneDeep } from 'lodash-es'; +import { filter, forEach } from '@/utils/helper/treeHelper'; +import { useGo } from '@/hooks/web/usePage'; +import { useScrollTo } from '@vben/hooks'; +import { onKeyStroke, useDebounceFn } from '@vueuse/core'; +import { useI18n } from '@/hooks/web/useI18n'; + +export interface SearchResult { + name: string; + path: string; + icon?: string; +} + +// Translate special characters +function transform(c: string) { + const code: string[] = ['$', '(', ')', '*', '+', '.', '[', ']', '?', '\\', '^', '{', '}', '|']; + return code.includes(c) ? `\\${c}` : c; +} + +function createSearchReg(key: string) { + const keys = [...key].map((item) => transform(item)); + const str = ['', ...keys, ''].join('.*'); + return new RegExp(str); +} + +export function useMenuSearch(refs: Ref, scrollWrap: Ref, emit: AnyFunction) { + const searchResult = ref([]); + const keyword = ref(''); + const activeIndex = ref(-1); + + let menuList: Menu[] = []; + + const { t } = useI18n(); + const go = useGo(); + const handleSearch = useDebounceFn(search, 200); + + onBeforeMount(async () => { + const list = await getMenus(); + menuList = cloneDeep(list); + forEach(menuList, (item) => { + item.name = t(item.name); + }); + }); + + function search(e: ChangeEvent) { + e?.stopPropagation(); + const key = e.target.value; + keyword.value = key.trim(); + if (!key) { + searchResult.value = []; + return; + } + const reg = createSearchReg(unref(keyword)); + const filterMenu = filter(menuList, (item) => { + return reg.test(item.name) && !item.hideMenu; + }); + searchResult.value = handlerSearchResult(filterMenu, reg); + activeIndex.value = 0; + } + + function handlerSearchResult(filterMenu: Menu[], reg: RegExp, parent?: Menu) { + const ret: SearchResult[] = []; + filterMenu.forEach((item) => { + const { name, path, icon, children, hideMenu, meta } = item; + if (!hideMenu && reg.test(name) && (!children?.length || meta?.hideChildrenInMenu)) { + ret.push({ + name: parent?.name ? `${parent.name} > ${name}` : name, + path, + icon, + }); + } + if (!meta?.hideChildrenInMenu && Array.isArray(children) && children.length) { + ret.push(...handlerSearchResult(children, reg, item)); + } + }); + return ret; + } + + // Activate when the mouse moves to a certain line + function handleMouseenter(e: any) { + const index = e.target.dataset.index; + activeIndex.value = Number(index); + } + + // Arrow key up + function handleUp() { + if (!searchResult.value.length) return; + activeIndex.value--; + if (activeIndex.value < 0) { + activeIndex.value = searchResult.value.length - 1; + } + handleScroll(); + } + + // Arrow key down + function handleDown() { + if (!searchResult.value.length) return; + activeIndex.value++; + if (activeIndex.value > searchResult.value.length - 1) { + activeIndex.value = 0; + } + handleScroll(); + } + + // When the keyboard up and down keys move to an invisible place + // the scroll bar needs to scroll automatically + function handleScroll() { + const refList = unref(refs); + if (!refList || !Array.isArray(refList) || refList.length === 0 || !unref(scrollWrap)) { + return; + } + + const index = unref(activeIndex); + const currentRef = refList[index]; + if (!currentRef) { + return; + } + const wrapEl = unref(scrollWrap); + if (!wrapEl) { + return; + } + const scrollHeight = currentRef.offsetTop + currentRef.offsetHeight; + const wrapHeight = wrapEl.offsetHeight; + const { start } = useScrollTo({ + el: wrapEl, + duration: 100, + to: scrollHeight - wrapHeight, + }); + start(); + } + + // enter keyboard event + async function handleEnter() { + if (!searchResult.value.length) { + return; + } + const result = unref(searchResult); + const index = unref(activeIndex); + if (result.length === 0 || index < 0) { + return; + } + const to = result[index]; + handleClose(); + await nextTick(); + go(to.path); + } + + // close search modal + function handleClose() { + searchResult.value = []; + emit('close'); + } + + // enter search + onKeyStroke('Enter', handleEnter); + // Monitor keyboard arrow keys + onKeyStroke('ArrowUp', handleUp); + onKeyStroke('ArrowDown', handleDown); + // esc close + onKeyStroke('Escape', handleClose); + + return { handleSearch, searchResult, keyword, activeIndex, handleMouseenter, handleEnter }; +} diff --git a/src/components/Application/src/useAppContext.ts b/src/components/Application/src/useAppContext.ts new file mode 100644 index 0000000..5356cdb --- /dev/null +++ b/src/components/Application/src/useAppContext.ts @@ -0,0 +1,17 @@ +import { InjectionKey, Ref } from 'vue'; +import { createContext, useContext } from '@/hooks/core/useContext'; + +export interface AppProviderContextProps { + prefixCls: Ref; + isMobile: Ref; +} + +const key: InjectionKey = Symbol(); + +export function createAppProviderContext(context: AppProviderContextProps) { + return createContext(context, key); +} + +export function useAppProviderContext() { + return useContext(key); +} diff --git a/src/components/Audit/ImportDataModal/AllocationModal/index.vue b/src/components/Audit/ImportDataModal/AllocationModal/index.vue new file mode 100644 index 0000000..79665b7 --- /dev/null +++ b/src/components/Audit/ImportDataModal/AllocationModal/index.vue @@ -0,0 +1,83 @@ + + + + + diff --git a/src/components/Audit/ImportDataModal/index.vue b/src/components/Audit/ImportDataModal/index.vue new file mode 100644 index 0000000..7943483 --- /dev/null +++ b/src/components/Audit/ImportDataModal/index.vue @@ -0,0 +1,103 @@ + + + + + diff --git a/src/components/Audit/InfoModal/index.vue b/src/components/Audit/InfoModal/index.vue new file mode 100644 index 0000000..d82e9e7 --- /dev/null +++ b/src/components/Audit/InfoModal/index.vue @@ -0,0 +1,602 @@ + + + + diff --git a/src/components/Tinymce/src/ImgUpload.vue b/src/components/Tinymce/src/ImgUpload.vue new file mode 100644 index 0000000..45c049b --- /dev/null +++ b/src/components/Tinymce/src/ImgUpload.vue @@ -0,0 +1,86 @@ + + + diff --git a/src/components/Tinymce/src/helper.ts b/src/components/Tinymce/src/helper.ts new file mode 100644 index 0000000..2526ae7 --- /dev/null +++ b/src/components/Tinymce/src/helper.ts @@ -0,0 +1,81 @@ +const validEvents = [ + 'onActivate', + 'onAddUndo', + 'onBeforeAddUndo', + 'onBeforeExecCommand', + 'onBeforeGetContent', + 'onBeforeRenderUI', + 'onBeforeSetContent', + 'onBeforePaste', + 'onBlur', + 'onChange', + 'onClearUndos', + 'onClick', + 'onContextMenu', + 'onCopy', + 'onCut', + 'onDblclick', + 'onDeactivate', + 'onDirty', + 'onDrag', + 'onDragDrop', + 'onDragEnd', + 'onDragGesture', + 'onDragOver', + 'onDrop', + 'onExecCommand', + 'onFocus', + 'onFocusIn', + 'onFocusOut', + 'onGetContent', + 'onHide', + 'onInit', + 'onKeyDown', + 'onKeyPress', + 'onKeyUp', + 'onLoadContent', + 'onMouseDown', + 'onMouseEnter', + 'onMouseLeave', + 'onMouseMove', + 'onMouseOut', + 'onMouseOver', + 'onMouseUp', + 'onNodeChange', + 'onObjectResizeStart', + 'onObjectResized', + 'onObjectSelected', + 'onPaste', + 'onPostProcess', + 'onPostRender', + 'onPreProcess', + 'onProgressState', + 'onRedo', + 'onRemove', + 'onReset', + 'onSaveContent', + 'onSelectionChange', + 'onSetAttrib', + 'onSetContent', + 'onShow', + 'onSubmit', + 'onUndo', + 'onVisualAid', +]; + +const isValidKey = (key: string) => validEvents.indexOf(key) !== -1; + +export const bindHandlers = (initEvent: Event, listeners: any, editor: any): void => { + Object.keys(listeners) + .filter(isValidKey) + .forEach((key: string) => { + const handler = listeners[key]; + if (typeof handler === 'function') { + if (key === 'onInit') { + handler(initEvent, editor); + } else { + editor.on(key.substring(2), (e: any) => handler(e, editor)); + } + } + }); +}; diff --git a/src/components/Tinymce/src/tinymce.ts b/src/components/Tinymce/src/tinymce.ts new file mode 100644 index 0000000..1374b4d --- /dev/null +++ b/src/components/Tinymce/src/tinymce.ts @@ -0,0 +1,13 @@ +// Any plugins you want to setting has to be imported +// Detail plugins list see https://www.tinymce.com/docs/plugins/ +// Custom builds see https://www.tinymce.com/download/custom-builds/ +// colorpicker/contextmenu/textcolor plugin is now built in to the core editor, please remove it from your editor configuration + +export const plugins = [ + 'advlist anchor autolink autosave code codesample directionality fullscreen hr insertdatetime link lists media nonbreaking noneditable pagebreak paste preview print save searchreplace spellchecker tabfocus template textpattern visualblocks visualchars wordcount', +]; + +export const toolbar = [ + 'fontsizeselect lineheight searchreplace bold italic underline strikethrough alignleft aligncenter alignright outdent indent blockquote undo redo removeformat subscript superscript code codesample', + 'hr bullist numlist link preview anchor pagebreak insertdatetime media forecolor backcolor fullscreen', +]; diff --git a/src/components/Transition/index.ts b/src/components/Transition/index.ts new file mode 100644 index 0000000..7eb79b5 --- /dev/null +++ b/src/components/Transition/index.ts @@ -0,0 +1,27 @@ +import { createSimpleTransition, createJavascriptTransition } from './src/CreateTransition'; + +import ExpandTransitionGenerator from './src/ExpandTransition'; + +export { default as CollapseTransition } from './src/CollapseTransition.vue'; + +export const FadeTransition = createSimpleTransition('fade-transition'); +export const ScaleTransition = createSimpleTransition('scale-transition'); +export const SlideYTransition = createSimpleTransition('slide-y-transition'); +export const ScrollYTransition = createSimpleTransition('scroll-y-transition'); +export const SlideYReverseTransition = createSimpleTransition('slide-y-reverse-transition'); +export const ScrollYReverseTransition = createSimpleTransition('scroll-y-reverse-transition'); +export const SlideXTransition = createSimpleTransition('slide-x-transition'); +export const ScrollXTransition = createSimpleTransition('scroll-x-transition'); +export const SlideXReverseTransition = createSimpleTransition('slide-x-reverse-transition'); +export const ScrollXReverseTransition = createSimpleTransition('scroll-x-reverse-transition'); +export const ScaleRotateTransition = createSimpleTransition('scale-rotate-transition'); + +export const ExpandXTransition = createJavascriptTransition( + 'expand-x-transition', + ExpandTransitionGenerator('', true), +); + +export const ExpandTransition = createJavascriptTransition( + 'expand-transition', + ExpandTransitionGenerator(''), +); diff --git a/src/components/Transition/src/CollapseTransition.vue b/src/components/Transition/src/CollapseTransition.vue new file mode 100644 index 0000000..853465b --- /dev/null +++ b/src/components/Transition/src/CollapseTransition.vue @@ -0,0 +1,72 @@ + + diff --git a/src/components/Transition/src/CreateTransition.tsx b/src/components/Transition/src/CreateTransition.tsx new file mode 100644 index 0000000..99cd2a9 --- /dev/null +++ b/src/components/Transition/src/CreateTransition.tsx @@ -0,0 +1,73 @@ +import type { PropType } from 'vue'; + +import { defineComponent, Transition, TransitionGroup } from 'vue'; +import { getSlot } from '@/utils/helper/tsxHelper'; + +type Mode = 'in-out' | 'out-in' | 'default' | undefined; + +export function createSimpleTransition(name: string, origin = 'top center 0', mode?: Mode) { + return defineComponent({ + name, + props: { + group: { + type: Boolean as PropType, + default: false, + }, + mode: { + type: String as PropType, + default: mode, + }, + origin: { + type: String as PropType, + default: origin, + }, + }, + setup(props, { slots, attrs }) { + const onBeforeEnter = (el: Element) => { + (el as HTMLElement).style.transformOrigin = props.origin; + }; + + return () => { + const Tag = !props.group ? Transition : TransitionGroup; + return ( + + {() => getSlot(slots)} + + ); + }; + }, + }); +} +export function createJavascriptTransition( + name: string, + functions: Recordable, + mode: Mode = 'in-out', +) { + return defineComponent({ + name, + props: { + mode: { + type: String as PropType, + default: mode, + }, + }, + setup(props, { attrs, slots }) { + return () => { + return ( + + {() => getSlot(slots)} + + ); + }; + }, + }); +} diff --git a/src/components/Transition/src/ExpandTransition.ts b/src/components/Transition/src/ExpandTransition.ts new file mode 100644 index 0000000..2aaef9a --- /dev/null +++ b/src/components/Transition/src/ExpandTransition.ts @@ -0,0 +1,89 @@ +/** + * Makes the first character of a string uppercase + */ +export function upperFirst(str: string): string { + return str.charAt(0).toUpperCase() + str.slice(1); +} + +interface HTMLExpandElement extends HTMLElement { + _parent?: (Node & ParentNode & HTMLElement) | null; + _initialStyle: { + transition: string; + overflow: string | null; + height?: string | null; + width?: string | null; + }; +} + +export default function (expandedParentClass = '', x = false) { + const sizeProperty = x ? 'width' : ('height' as 'width' | 'height'); + const offsetProperty = `offset${upperFirst(sizeProperty)}` as 'offsetHeight' | 'offsetWidth'; + + return { + beforeEnter(el: HTMLExpandElement) { + el._parent = el.parentNode as (Node & ParentNode & HTMLElement) | null; + el._initialStyle = { + transition: el.style.transition, + overflow: el.style.overflow, + [sizeProperty]: el.style[sizeProperty], + }; + }, + + enter(el: HTMLExpandElement) { + const initialStyle = el._initialStyle; + + el.style.setProperty('transition', 'none', 'important'); + el.style.overflow = 'hidden'; + // const offset = `${el[offsetProperty]}px`; + + // el.style[sizeProperty] = '0'; + + void el.offsetHeight; // force reflow + + el.style.transition = initialStyle.transition; + + if (expandedParentClass && el._parent) { + el._parent.classList.add(expandedParentClass); + } + + requestAnimationFrame(() => { + // el.style[sizeProperty] = offset; + }); + }, + + afterEnter: resetStyles, + enterCancelled: resetStyles, + + leave(el: HTMLExpandElement) { + el._initialStyle = { + transition: '', + overflow: el.style.overflow, + [sizeProperty]: el.style[sizeProperty], + }; + + el.style.overflow = 'hidden'; + el.style[sizeProperty] = `${el[offsetProperty]}px`; + /* eslint-disable-next-line */ + void el.offsetHeight; // force reflow + + requestAnimationFrame(() => (el.style[sizeProperty] = '0')); + }, + + afterLeave, + leaveCancelled: afterLeave, + }; + + function afterLeave(el: HTMLExpandElement) { + if (expandedParentClass && el._parent) { + el._parent.classList.remove(expandedParentClass); + } + resetStyles(el); + } + + function resetStyles(el: HTMLExpandElement) { + const size = el._initialStyle[sizeProperty]; + el.style.overflow = el._initialStyle.overflow!; + if (size != null) el.style[sizeProperty] = size; + Reflect.deleteProperty(el, '_initialStyle'); + } +} diff --git a/src/components/Tree/index.ts b/src/components/Tree/index.ts new file mode 100644 index 0000000..70dcb03 --- /dev/null +++ b/src/components/Tree/index.ts @@ -0,0 +1,6 @@ +import BasicTree from './src/BasicTree.vue'; +import './style'; + +export { BasicTree }; +export type { ContextMenuItem } from '@/hooks/web/useContextMenu'; +export * from './src/types/tree'; diff --git a/src/components/Tree/src/BasicTree.vue b/src/components/Tree/src/BasicTree.vue new file mode 100644 index 0000000..c6686ab --- /dev/null +++ b/src/components/Tree/src/BasicTree.vue @@ -0,0 +1,575 @@ + + + diff --git a/src/components/Tree/src/TreeIcon.ts b/src/components/Tree/src/TreeIcon.ts new file mode 100644 index 0000000..5f3e765 --- /dev/null +++ b/src/components/Tree/src/TreeIcon.ts @@ -0,0 +1,12 @@ +import type { VNode } from 'vue'; +import { h } from 'vue'; +import { isString } from 'lodash-es'; +import Icon from '@/components/Icon/Icon.vue'; + +export const TreeIcon = ({ icon }: { icon: VNode | string | undefined }) => { + if (!icon) return null; + if (isString(icon)) { + return h(Icon, { icon, class: 'mr-2' }); + } + return h(Icon); +}; diff --git a/src/components/Tree/src/components/TreeHeader.vue b/src/components/Tree/src/components/TreeHeader.vue new file mode 100644 index 0000000..05b15cf --- /dev/null +++ b/src/components/Tree/src/components/TreeHeader.vue @@ -0,0 +1,181 @@ + + + diff --git a/src/components/Tree/src/hooks/useTree.ts b/src/components/Tree/src/hooks/useTree.ts new file mode 100644 index 0000000..b7621cf --- /dev/null +++ b/src/components/Tree/src/hooks/useTree.ts @@ -0,0 +1,211 @@ +import type { InsertNodeParams, KeyType, FieldNames, TreeItem } from '../types/tree'; +import type { Ref, ComputedRef } from 'vue'; +import type { TreeDataItem } from 'ant-design-vue/es/tree/Tree'; + +import { cloneDeep } from 'lodash-es'; +import { unref } from 'vue'; +import { forEach } from '@/utils/helper/treeHelper'; + +export function useTree(treeDataRef: Ref, getFieldNames: ComputedRef) { + function getAllKeys(list?: TreeDataItem[]) { + const keys: string[] = []; + const treeData = list || unref(treeDataRef); + const { key: keyField, children: childrenField } = unref(getFieldNames); + if (!childrenField || !keyField) return keys; + + for (let index = 0; index < treeData.length; index++) { + const node = treeData[index]; + keys.push(node[keyField]!); + const children = node[childrenField]; + if (children && children.length) { + keys.push(...(getAllKeys(children) as string[])); + } + } + return keys as KeyType[]; + } + + // get keys that can be checked and selected + function getEnabledKeys(list?: TreeDataItem[]) { + const keys: string[] = []; + const treeData = list || unref(treeDataRef); + const { key: keyField, children: childrenField } = unref(getFieldNames); + if (!childrenField || !keyField) return keys; + + for (let index = 0; index < treeData.length; index++) { + const node = treeData[index]; + node.disabled !== true && node.selectable !== false && keys.push(node[keyField]!); + const children = node[childrenField]; + if (children && children.length) { + keys.push(...(getEnabledKeys(children) as string[])); + } + } + return keys as KeyType[]; + } + + function getChildrenKeys(nodeKey: string | number, list?: TreeDataItem[]) { + const keys: KeyType[] = []; + const treeData = list || unref(treeDataRef); + const { key: keyField, children: childrenField } = unref(getFieldNames); + if (!childrenField || !keyField) return keys; + for (let index = 0; index < treeData.length; index++) { + const node = treeData[index]; + const children = node[childrenField]; + if (nodeKey === node[keyField]) { + keys.push(node[keyField]!); + if (children && children.length) { + keys.push(...(getAllKeys(children) as string[])); + } + } else { + if (children && children.length) { + keys.push(...getChildrenKeys(nodeKey, children)); + } + } + } + return keys as KeyType[]; + } + + // Update node + function updateNodeByKey(key: string, node: Omit, list?: TreeDataItem[]) { + if (!key) return; + const treeData = list || unref(treeDataRef); + const { key: keyField, children: childrenField } = unref(getFieldNames); + + if (!childrenField || !keyField) return; + + for (let index = 0; index < treeData.length; index++) { + const element: any = treeData[index]; + const children = element[childrenField]; + + if (element[keyField] === key) { + treeData[index] = { ...treeData[index], ...node }; + break; + } else if (children && children.length) { + updateNodeByKey(key, node, element[childrenField]); + } + } + } + + // Expand the specified level + function filterByLevel(level = 1, list?: TreeDataItem[], currentLevel = 1) { + if (!level) { + return []; + } + const res: (string | number)[] = []; + const data = list || unref(treeDataRef) || []; + for (let index = 0; index < data.length; index++) { + const item = data[index]; + + const { key: keyField, children: childrenField } = unref(getFieldNames); + const key = keyField ? item[keyField] : ''; + const children = childrenField ? item[childrenField] : []; + res.push(key); + if (children && children.length && currentLevel < level) { + currentLevel += 1; + res.push(...filterByLevel(level, children, currentLevel)); + } + } + return res as string[] | number[]; + } + + /** + * 添加节点 + */ + function insertNodeByKey({ parentKey = null, node, push = 'push' }: InsertNodeParams) { + const treeData: any = cloneDeep(unref(treeDataRef)); + if (!parentKey) { + treeData[push](node); + treeDataRef.value = treeData; + return; + } + const { key: keyField, children: childrenField } = unref(getFieldNames); + if (!childrenField || !keyField) return; + + forEach(treeData, (treeItem) => { + if (treeItem[keyField] === parentKey) { + treeItem[childrenField] = treeItem[childrenField] || []; + treeItem[childrenField][push](node); + return true; + } + }); + treeDataRef.value = treeData; + } + /** + * 批量添加节点 + */ + function insertNodesByKey({ parentKey = null, list, push = 'push' }: InsertNodeParams) { + const treeData: any = cloneDeep(unref(treeDataRef)); + if (!list || list.length < 1) { + return; + } + if (!parentKey) { + for (let i = 0; i < list.length; i++) { + treeData[push](list[i]); + } + treeDataRef.value = treeData; + return; + } else { + const { key: keyField, children: childrenField } = unref(getFieldNames); + if (!childrenField || !keyField) return; + + forEach(treeData, (treeItem) => { + if (treeItem[keyField] === parentKey) { + treeItem[childrenField] = treeItem[childrenField] || []; + for (let i = 0; i < list.length; i++) { + treeItem[childrenField][push](list[i]); + } + treeDataRef.value = treeData; + return true; + } + }); + } + } + // Delete node + function deleteNodeByKey(key: string, list?: TreeDataItem[]) { + if (!key) return; + const treeData = list || unref(treeDataRef); + const { key: keyField, children: childrenField } = unref(getFieldNames); + if (!childrenField || !keyField) return; + + for (let index = 0; index < treeData.length; index++) { + const element: any = treeData[index]; + const children = element[childrenField]; + + if (element[keyField] === key) { + treeData.splice(index, 1); + break; + } else if (children && children.length) { + deleteNodeByKey(key, element[childrenField]); + } + } + } + + // Get selected node + function getSelectedNode(key: KeyType, list?: TreeItem[], selectedNode?: TreeItem | null) { + if (!key && key !== 0) return null; + const treeData = list || unref(treeDataRef); + const { key: keyField, children: childrenField } = unref(getFieldNames); + if (!keyField) return null; + treeData.forEach((item) => { + if (selectedNode?.key || selectedNode?.key === 0) return selectedNode; + if (item[keyField] === key) { + selectedNode = item; + return; + } + if (item[childrenField!] && item[childrenField!].length) { + selectedNode = getSelectedNode(key, item[childrenField!], selectedNode); + } + }); + return selectedNode || null; + } + return { + deleteNodeByKey, + insertNodeByKey, + insertNodesByKey, + filterByLevel, + updateNodeByKey, + getAllKeys, + getChildrenKeys, + getEnabledKeys, + getSelectedNode, + }; +} diff --git a/src/components/Tree/src/types/tree.ts b/src/components/Tree/src/types/tree.ts new file mode 100644 index 0000000..604adb3 --- /dev/null +++ b/src/components/Tree/src/types/tree.ts @@ -0,0 +1,195 @@ +import type { ExtractPropTypes } from 'vue'; +import type { TreeDataItem } from 'ant-design-vue/es/tree/Tree'; + +import { buildProps } from '@/utils/props'; + +export enum ToolbarEnum { + SELECT_ALL, + UN_SELECT_ALL, + EXPAND_ALL, + UN_EXPAND_ALL, + CHECK_STRICTLY, + CHECK_UN_STRICTLY, +} + +export const treeEmits = [ + 'update:expandedKeys', + 'update:selectedKeys', + 'update:value', + 'change', + 'check', + 'update:searchValue', +]; + +export interface TreeState { + expandedKeys: KeyType[]; + selectedKeys: KeyType[]; + checkedKeys: CheckKeys; + checkStrictly: boolean; +} + +export interface FieldNames { + children?: string; + title?: string; + key?: string; +} + +export type KeyType = string | number; + +export type CheckKeys = + | KeyType[] + | { checked: string[] | number[]; halfChecked: string[] | number[] }; + +export const treeProps = buildProps({ + value: { + type: [Object, Array] as PropType, + }, + + renderIcon: { + type: Function as PropType<(...params: any[]) => string>, + }, + + helpMessage: { + type: [String, Array] as PropType, + default: '', + }, + + title: { + type: String, + default: '', + }, + toolbar: Boolean, + search: Boolean, + searchValue: { + type: String, + default: '', + }, + checkStrictly: Boolean, + clickRowToExpand: { + type: Boolean, + default: false, + }, + checkable: Boolean, + defaultExpandLevel: { + type: [String, Number] as PropType, + default: '', + }, + defaultExpandAll: Boolean, + + fieldNames: { + type: Object as PropType, + }, + + treeData: { + type: Array as PropType, + }, + + actionList: { + type: Array as PropType, + default: () => [], + }, + + expandedKeys: { + type: Array as PropType, + }, + + selectedKeys: { + type: Array as PropType, + default: () => [], + }, + + checkedKeys: { + type: [Array, Object] as PropType, + default: () => [], + }, + + beforeRightClick: { + type: Function as PropType<(...arg: any) => Promise>, + default: undefined, + }, + + rightMenuList: { + type: Array as PropType, + }, + // 自定义数据过滤判断方法(注: 不是整个过滤方法,而是内置过滤的判断方法,用于增强原本仅能通过title进行过滤的方式) + filterFn: { + type: Function as PropType< + (searchValue: any, node: TreeItem, fieldNames: FieldNames) => boolean + >, + default: undefined, + }, + // 高亮搜索值,仅高亮具体匹配值(通过title)值为true时使用默认色值,值为#xxx时使用此值替代且高亮开启 + highlight: { + type: [Boolean, String] as PropType, + default: false, + }, + // 搜索完成时自动展开结果 + expandOnSearch: Boolean, + // 搜索完成自动选中所有结果,当且仅当 checkable===true 时生效 + checkOnSearch: Boolean, + // 搜索完成自动select所有结果 + selectedOnSearch: Boolean, + loading: { + type: Boolean, + default: false, + }, + treeWrapperClassName: String, +}); + +export type TreeProps = ExtractPropTypes; + +export interface ContextMenuItem { + label: string; + icon?: string; + hidden?: boolean; + disabled?: boolean; + handler?: Fn; + divider?: boolean; + children?: ContextMenuItem[]; +} + +export interface ContextMenuOptions { + icon?: string; + styles?: any; + items?: ContextMenuItem[]; +} + +export interface TreeItem extends TreeDataItem { + icon?: any; +} + +export interface TreeActionItem { + render: (record: Recordable) => any; + show?: boolean | ((record: Recordable) => boolean); +} + +export interface InsertNodeParams { + parentKey: string | null; + node?: TreeDataItem; + list?: TreeDataItem[]; + push?: 'push' | 'unshift'; +} + +export interface TreeActionType { + getTreeData: () => TreeDataItem[]; + checkAll: (checkAll: boolean) => void; + expandAll: (expandAll: boolean) => void; + setExpandedKeys: (keys: KeyType[]) => void; + getExpandedKeys: () => KeyType[]; + setSelectedKeys: (keys: KeyType[]) => void; + getSelectedKeys: () => KeyType[]; + setCheckedKeys: (keys: CheckKeys) => void; + getCheckedKeys: () => CheckKeys; + filterByLevel: (level: number) => void; + insertNodeByKey: (opt: InsertNodeParams) => void; + insertNodesByKey: (opt: InsertNodeParams) => void; + deleteNodeByKey: (key: string, list?: TreeDataItem[]) => void; + updateNodeByKey: (key: string, node: Omit) => void; + setSearchValue: (value: string) => void; + getSearchValue: () => string; + getSelectedNode: ( + key: KeyType, + treeList?: TreeItem[], + selectNode?: TreeItem | null, + ) => TreeItem | null; +} diff --git a/src/components/Tree/style/index.less b/src/components/Tree/style/index.less new file mode 100644 index 0000000..b8e689b --- /dev/null +++ b/src/components/Tree/style/index.less @@ -0,0 +1,61 @@ +@tree-prefix-cls: ~'@{namespace}-tree'; + +.@{tree-prefix-cls} { + background-color: @component-background; + + .ant-tree { + .ant-tree-checkbox { + margin-block-start: 0; + margin-inline-start: 4px; + margin-inline-end: 4px; + + & + span { + padding-left: 4px; + } + } + } + + .ant-tree-node-content-wrapper { + position: relative; + + .ant-tree-title { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + } + + &__title { + display: flex; + position: relative; + align-items: center; + width: 100%; + padding-right: 10px; + + &:hover { + .@{tree-prefix-cls}__action { + visibility: visible; + } + } + } + + &__content { + overflow: hidden; + } + + &__actions { + display: flex; + position: absolute; + //top: 2px; + right: 3px; + } + + &__action { + visibility: hidden; + margin-left: 4px; + } + + &-header { + border-bottom: 1px solid @border-color-base; + } +} diff --git a/src/components/Tree/style/index.ts b/src/components/Tree/style/index.ts new file mode 100644 index 0000000..d74e52e --- /dev/null +++ b/src/components/Tree/style/index.ts @@ -0,0 +1 @@ +import './index.less'; diff --git a/src/components/Upload/index.ts b/src/components/Upload/index.ts new file mode 100644 index 0000000..ddbabfa --- /dev/null +++ b/src/components/Upload/index.ts @@ -0,0 +1,10 @@ +import { withInstall } from '@/utils'; +import basicUpload from './src/BasicUpload.vue'; +import uploadImage from './src/components/ImageUpload.vue'; +import uploadVideo from './src/components/VideoUpload.vue'; +import uploadFile from './src/components/FileUpload.vue' + +export const ImageUpload = withInstall(uploadImage); +export const BasicUpload = withInstall(basicUpload); +export const VideoUpload = withInstall(uploadVideo); +export const FileUpload = withInstall(uploadFile); diff --git a/src/components/Upload/src/BasicUpload.vue b/src/components/Upload/src/BasicUpload.vue new file mode 100644 index 0000000..25978cb --- /dev/null +++ b/src/components/Upload/src/BasicUpload.vue @@ -0,0 +1,109 @@ + + diff --git a/src/components/Upload/src/base64/base64.js b/src/components/Upload/src/base64/base64.js new file mode 100644 index 0000000..5ba02e9 --- /dev/null +++ b/src/components/Upload/src/base64/base64.js @@ -0,0 +1,317 @@ + + +// +// THIS FILE IS AUTOMATICALLY GENERATED! DO NOT EDIT BY HAND! +// +;(function(global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + ? module.exports = factory() + : typeof define === 'function' && define.amd + ? define(factory) : + // cf. https://github.com/dankogai/js-base64/issues/119 + (function() { + // existing version for noConflict() + const _Base64 = global.Base64; + const gBase64 = factory(); + gBase64.noConflict = () => { + global.Base64 = _Base64; + return gBase64; + }; + if (global.Meteor) { // Meteor.js + Base64 = gBase64; + } + global.Base64 = gBase64; + })(); +}((typeof self !== 'undefined' ? self + : typeof window !== 'undefined' ? window + : typeof global !== 'undefined' ? global + : this +), function() { + 'use strict'; + +/** + * base64.ts + * + * Licensed under the BSD 3-Clause License. + * http://opensource.org/licenses/BSD-3-Clause + * + * References: + * http://en.wikipedia.org/wiki/Base64 + * + * @author Dan Kogai (https://github.com/dankogai) + */ +const version = '3.6.0'; +/** + * @deprecated use lowercase `version`. + */ +const VERSION = version; +const _hasatob = typeof atob === 'function'; +const _hasbtoa = typeof btoa === 'function'; +const _hasBuffer = typeof Buffer === 'function'; +const _TD = typeof TextDecoder === 'function' ? new TextDecoder() : undefined; +const _TE = typeof TextEncoder === 'function' ? new TextEncoder() : undefined; +const b64ch = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; +const b64chs = [...b64ch]; +const b64tab = ((a) => { + let tab = {}; + a.forEach((c, i) => tab[c] = i); + return tab; +})(b64chs); +const b64re = /^(?:[A-Za-z\d+\/]{4})*?(?:[A-Za-z\d+\/]{2}(?:==)?|[A-Za-z\d+\/]{3}=?)?$/; +const _fromCC = String.fromCharCode.bind(String); +const _U8Afrom = typeof Uint8Array.from === 'function' + ? Uint8Array.from.bind(Uint8Array) + : (it, fn = (x) => x) => new Uint8Array(Array.prototype.slice.call(it, 0).map(fn)); +const _mkUriSafe = (src) => src + .replace(/[+\/]/g, (m0) => m0 == '+' ? '-' : '_') + .replace(/=+$/m, ''); +const _tidyB64 = (s) => s.replace(/[^A-Za-z0-9\+\/]/g, ''); +/** + * polyfill version of `btoa` + */ +const btoaPolyfill = (bin) => { + // console.log('polyfilled'); + let u32, c0, c1, c2, asc = ''; + const pad = bin.length % 3; + for (let i = 0; i < bin.length;) { + if ((c0 = bin.charCodeAt(i++)) > 255 || + (c1 = bin.charCodeAt(i++)) > 255 || + (c2 = bin.charCodeAt(i++)) > 255) + throw new TypeError('invalid character found'); + u32 = (c0 << 16) | (c1 << 8) | c2; + asc += b64chs[u32 >> 18 & 63] + + b64chs[u32 >> 12 & 63] + + b64chs[u32 >> 6 & 63] + + b64chs[u32 & 63]; + } + return pad ? asc.slice(0, pad - 3) + "===".substring(pad) : asc; +}; +/** + * does what `window.btoa` of web browsers do. + * @param {String} bin binary string + * @returns {string} Base64-encoded string + */ +const _btoa = _hasbtoa ? (bin) => btoa(bin) + : _hasBuffer ? (bin) => Buffer.from(bin, 'binary').toString('base64') + : btoaPolyfill; +const _fromUint8Array = _hasBuffer + ? (u8a) => Buffer.from(u8a).toString('base64') + : (u8a) => { + // cf. https://stackoverflow.com/questions/12710001/how-to-convert-uint8-array-to-base64-encoded-string/12713326#12713326 + const maxargs = 0x1000; + let strs = []; + for (let i = 0, l = u8a.length; i < l; i += maxargs) { + strs.push(_fromCC.apply(null, u8a.subarray(i, i + maxargs))); + } + return _btoa(strs.join('')); + }; +/** + * converts a Uint8Array to a Base64 string. + * @param {boolean} [urlsafe] URL-and-filename-safe a la RFC4648 §5 + * @returns {string} Base64 string + */ +const fromUint8Array = (u8a, urlsafe = false) => urlsafe ? _mkUriSafe(_fromUint8Array(u8a)) : _fromUint8Array(u8a); +// This trick is found broken https://github.com/dankogai/js-base64/issues/130 +// const utob = (src: string) => unescape(encodeURIComponent(src)); +// reverting good old fationed regexp +const cb_utob = (c) => { + if (c.length < 2) { + var cc = c.charCodeAt(0); + return cc < 0x80 ? c + : cc < 0x800 ? (_fromCC(0xc0 | (cc >>> 6)) + + _fromCC(0x80 | (cc & 0x3f))) + : (_fromCC(0xe0 | ((cc >>> 12) & 0x0f)) + + _fromCC(0x80 | ((cc >>> 6) & 0x3f)) + + _fromCC(0x80 | (cc & 0x3f))); + } + else { + var cc = 0x10000 + + (c.charCodeAt(0) - 0xD800) * 0x400 + + (c.charCodeAt(1) - 0xDC00); + return (_fromCC(0xf0 | ((cc >>> 18) & 0x07)) + + _fromCC(0x80 | ((cc >>> 12) & 0x3f)) + + _fromCC(0x80 | ((cc >>> 6) & 0x3f)) + + _fromCC(0x80 | (cc & 0x3f))); + } +}; +const re_utob = /[\uD800-\uDBFF][\uDC00-\uDFFFF]|[^\x00-\x7F]/g; +/** + * @deprecated should have been internal use only. + * @param {string} src UTF-8 string + * @returns {string} UTF-16 string + */ +const utob = (u) => u.replace(re_utob, cb_utob); +// +const _encode = _hasBuffer + ? (s) => Buffer.from(s, 'utf8').toString('base64') + : _TE + ? (s) => _fromUint8Array(_TE.encode(s)) + : (s) => _btoa(utob(s)); +/** + * converts a UTF-8-encoded string to a Base64 string. + * @param {boolean} [urlsafe] if `true` make the result URL-safe + * @returns {string} Base64 string + */ +const encode = (src, urlsafe = false) => urlsafe + ? _mkUriSafe(_encode(src)) + : _encode(src); +/** + * converts a UTF-8-encoded string to URL-safe Base64 RFC4648 §5. + * @returns {string} Base64 string + */ +const encodeURI = (src) => encode(src, true); +// This trick is found broken https://github.com/dankogai/js-base64/issues/130 +// const btou = (src: string) => decodeURIComponent(escape(src)); +// reverting good old fationed regexp +const re_btou = /[\xC0-\xDF][\x80-\xBF]|[\xE0-\xEF][\x80-\xBF]{2}|[\xF0-\xF7][\x80-\xBF]{3}/g; +const cb_btou = (cccc) => { + switch (cccc.length) { + case 4: + var cp = ((0x07 & cccc.charCodeAt(0)) << 18) + | ((0x3f & cccc.charCodeAt(1)) << 12) + | ((0x3f & cccc.charCodeAt(2)) << 6) + | (0x3f & cccc.charCodeAt(3)), offset = cp - 0x10000; + return (_fromCC((offset >>> 10) + 0xD800) + + _fromCC((offset & 0x3FF) + 0xDC00)); + case 3: + return _fromCC(((0x0f & cccc.charCodeAt(0)) << 12) + | ((0x3f & cccc.charCodeAt(1)) << 6) + | (0x3f & cccc.charCodeAt(2))); + default: + return _fromCC(((0x1f & cccc.charCodeAt(0)) << 6) + | (0x3f & cccc.charCodeAt(1))); + } +}; +/** + * @deprecated should have been internal use only. + * @param {string} src UTF-16 string + * @returns {string} UTF-8 string + */ +const btou = (b) => b.replace(re_btou, cb_btou); +/** + * polyfill version of `atob` + */ +const atobPolyfill = (asc) => { + // console.log('polyfilled'); + asc = asc.replace(/\s+/g, ''); + if (!b64re.test(asc)) + throw new TypeError('malformed base64.'); + asc += '=='.slice(2 - (asc.length & 3)); + let u24, bin = '', r1, r2; + for (let i = 0; i < asc.length;) { + u24 = b64tab[asc.charAt(i++)] << 18 + | b64tab[asc.charAt(i++)] << 12 + | (r1 = b64tab[asc.charAt(i++)]) << 6 + | (r2 = b64tab[asc.charAt(i++)]); + bin += r1 === 64 ? _fromCC(u24 >> 16 & 255) + : r2 === 64 ? _fromCC(u24 >> 16 & 255, u24 >> 8 & 255) + : _fromCC(u24 >> 16 & 255, u24 >> 8 & 255, u24 & 255); + } + return bin; +}; +/** + * does what `window.atob` of web browsers do. + * @param {String} asc Base64-encoded string + * @returns {string} binary string + */ +const _atob = _hasatob ? (asc) => atob(_tidyB64(asc)) + : _hasBuffer ? (asc) => Buffer.from(asc, 'base64').toString('binary') + : atobPolyfill; +// +const _toUint8Array = _hasBuffer + ? (a) => _U8Afrom(Buffer.from(a, 'base64')) + : (a) => _U8Afrom(_atob(a), c => c.charCodeAt(0)); +/** + * converts a Base64 string to a Uint8Array. + */ +const toUint8Array = (a) => _toUint8Array(_unURI(a)); +// +const _decode = _hasBuffer + ? (a) => Buffer.from(a, 'base64').toString('utf8') + : _TD + ? (a) => _TD.decode(_toUint8Array(a)) + : (a) => btou(_atob(a)); +const _unURI = (a) => _tidyB64(a.replace(/[-_]/g, (m0) => m0 == '-' ? '+' : '/')); +/** + * converts a Base64 string to a UTF-8 string. + * @param {String} src Base64 string. Both normal and URL-safe are supported + * @returns {string} UTF-8 string + */ +const decode = (src) => _decode(_unURI(src)); +/** + * check if a value is a valid Base64 string + * @param {String} src a value to check + */ +const isValid = (src) => { + if (typeof src !== 'string') + return false; + const s = src.replace(/\s+/g, '').replace(/=+$/, ''); + return !/[^\s0-9a-zA-Z\+/]/.test(s) || !/[^\s0-9a-zA-Z\-_]/.test(s); +}; +// +const _noEnum = (v) => { + return { + value: v, enumerable: false, writable: true, configurable: true + }; +}; +/** + * extend String.prototype with relevant methods + */ +const extendString = function () { + const _add = (name, body) => Object.defineProperty(String.prototype, name, _noEnum(body)); + _add('fromBase64', function () { return decode(this); }); + _add('toBase64', function (urlsafe) { return encode(this, urlsafe); }); + _add('toBase64URI', function () { return encode(this, true); }); + _add('toBase64URL', function () { return encode(this, true); }); + _add('toUint8Array', function () { return toUint8Array(this); }); +}; +/** + * extend Uint8Array.prototype with relevant methods + */ +const extendUint8Array = function () { + const _add = (name, body) => Object.defineProperty(Uint8Array.prototype, name, _noEnum(body)); + _add('toBase64', function (urlsafe) { return fromUint8Array(this, urlsafe); }); + _add('toBase64URI', function () { return fromUint8Array(this, true); }); + _add('toBase64URL', function () { return fromUint8Array(this, true); }); +}; +/** + * extend Builtin prototypes with relevant methods + */ +const extendBuiltins = () => { + extendString(); + extendUint8Array(); +}; +const gBase64 = { + version: version, + VERSION: VERSION, + atob: _atob, + atobPolyfill: atobPolyfill, + btoa: _btoa, + btoaPolyfill: btoaPolyfill, + fromBase64: decode, + toBase64: encode, + encode: encode, + encodeURI: encodeURI, + encodeURL: encodeURI, + utob: utob, + btou: btou, + decode: decode, + isValid: isValid, + fromUint8Array: fromUint8Array, + toUint8Array: toUint8Array, + extendString: extendString, + extendUint8Array: extendUint8Array, + extendBuiltins: extendBuiltins, +}; + + // + // export Base64 to the namespace + // + // ES5 is yet to have Object.assign() that may make transpilers unhappy. + // gBase64.Base64 = Object.assign({}, gBase64); + gBase64.Base64 = {}; + Object.keys(gBase64).forEach(k => gBase64.Base64[k] = gBase64[k]); + return gBase64; +})); + + diff --git a/src/components/Upload/src/components/AuthImage.vue b/src/components/Upload/src/components/AuthImage.vue new file mode 100644 index 0000000..3e2591c --- /dev/null +++ b/src/components/Upload/src/components/AuthImage.vue @@ -0,0 +1,146 @@ + + + + + \ No newline at end of file diff --git a/src/components/Upload/src/components/Base64Image.vue b/src/components/Upload/src/components/Base64Image.vue new file mode 100644 index 0000000..97b0f96 --- /dev/null +++ b/src/components/Upload/src/components/Base64Image.vue @@ -0,0 +1,54 @@ + + + + + \ No newline at end of file diff --git a/src/components/Upload/src/components/FileList.vue b/src/components/Upload/src/components/FileList.vue new file mode 100644 index 0000000..4c545bf --- /dev/null +++ b/src/components/Upload/src/components/FileList.vue @@ -0,0 +1,139 @@ + + diff --git a/src/components/Upload/src/components/FilePreview.vue b/src/components/Upload/src/components/FilePreview.vue new file mode 100644 index 0000000..6178c08 --- /dev/null +++ b/src/components/Upload/src/components/FilePreview.vue @@ -0,0 +1,35 @@ + + + \ No newline at end of file diff --git a/src/components/Upload/src/components/FileUpload.vue b/src/components/Upload/src/components/FileUpload.vue new file mode 100644 index 0000000..4c9e2d4 --- /dev/null +++ b/src/components/Upload/src/components/FileUpload.vue @@ -0,0 +1,372 @@ + + + + + + diff --git a/src/components/Upload/src/components/FileUploadSelectOtherModal.vue b/src/components/Upload/src/components/FileUploadSelectOtherModal.vue new file mode 100644 index 0000000..568d35b --- /dev/null +++ b/src/components/Upload/src/components/FileUploadSelectOtherModal.vue @@ -0,0 +1,152 @@ + + + + + diff --git a/src/components/Upload/src/components/ImageUpload.vue b/src/components/Upload/src/components/ImageUpload.vue new file mode 100644 index 0000000..c5094f6 --- /dev/null +++ b/src/components/Upload/src/components/ImageUpload.vue @@ -0,0 +1,478 @@ + + + + + diff --git a/src/components/Upload/src/components/ImageUploadSelectOtherModal.vue b/src/components/Upload/src/components/ImageUploadSelectOtherModal.vue new file mode 100644 index 0000000..9ffaee1 --- /dev/null +++ b/src/components/Upload/src/components/ImageUploadSelectOtherModal.vue @@ -0,0 +1,155 @@ + + + + + diff --git a/src/components/Upload/src/components/ThumbUrl.vue b/src/components/Upload/src/components/ThumbUrl.vue new file mode 100644 index 0000000..e4bc577 --- /dev/null +++ b/src/components/Upload/src/components/ThumbUrl.vue @@ -0,0 +1,25 @@ + + + diff --git a/src/components/Upload/src/components/UploadModal.vue b/src/components/Upload/src/components/UploadModal.vue new file mode 100644 index 0000000..5b14988 --- /dev/null +++ b/src/components/Upload/src/components/UploadModal.vue @@ -0,0 +1,294 @@ + + + diff --git a/src/components/Upload/src/components/UploadPreviewModal.vue b/src/components/Upload/src/components/UploadPreviewModal.vue new file mode 100644 index 0000000..cec69fb --- /dev/null +++ b/src/components/Upload/src/components/UploadPreviewModal.vue @@ -0,0 +1,81 @@ + + + diff --git a/src/components/Upload/src/components/VideoUpload.vue b/src/components/Upload/src/components/VideoUpload.vue new file mode 100644 index 0000000..0826e2a --- /dev/null +++ b/src/components/Upload/src/components/VideoUpload.vue @@ -0,0 +1,302 @@ + + + + + diff --git a/src/components/Upload/src/components/data.tsx b/src/components/Upload/src/components/data.tsx new file mode 100644 index 0000000..7c6415d --- /dev/null +++ b/src/components/Upload/src/components/data.tsx @@ -0,0 +1,139 @@ +import type { BasicColumn, ActionItem } from '@/components/Table'; +import { FileBasicColumn, FileItem, PreviewFileItem, UploadResultStatus } from '../types/typing'; +import { isImgTypeByName } from '../helper'; +import { Progress, Tag } from 'ant-design-vue'; +import TableAction from '@/components/Table/src/components/TableAction.vue'; +import ThumbUrl from './ThumbUrl.vue'; +import { useI18n } from '@/hooks/web/useI18n'; + +const { t } = useI18n(); + +// 文件上传列表 +export function createTableColumns(): FileBasicColumn[] { + return [ + { + dataIndex: 'thumbUrl', + title: t('component.upload.legend'), + width: 100, + customRender: ({ record }) => { + const { thumbUrl } = (record as FileItem) || {}; + return thumbUrl && ; + }, + }, + { + dataIndex: 'name', + title: t('component.upload.fileName'), + align: 'left', + customRender: ({ text, record }) => { + const { percent, status: uploadStatus } = (record as FileItem) || {}; + let status: 'normal' | 'exception' | 'active' | 'success' = 'normal'; + if (uploadStatus === UploadResultStatus.ERROR) { + status = 'exception'; + } else if (uploadStatus === UploadResultStatus.UPLOADING) { + status = 'active'; + } else if (uploadStatus === UploadResultStatus.SUCCESS) { + status = 'success'; + } + return ( +
+

+ {text} +

+ +
+ ); + }, + }, + { + dataIndex: 'size', + title: t('component.upload.fileSize'), + width: 100, + customRender: ({ text = 0 }) => { + return text && (text / 1024).toFixed(2) + 'KB'; + }, + }, + { + dataIndex: 'status', + title: t('component.upload.fileStatue'), + width: 100, + customRender: ({ text }) => { + if (text === UploadResultStatus.SUCCESS) { + return {() => t('component.upload.uploadSuccess')}; + } else if (text === UploadResultStatus.ERROR) { + return {() => t('component.upload.uploadError')}; + } else if (text === UploadResultStatus.UPLOADING) { + return {() => t('component.upload.uploading')}; + } + + return text || t('component.upload.pending'); + }, + }, + ]; +} +export function createActionColumn(handleRemove: Function): FileBasicColumn { + return { + width: 120, + title: t('component.upload.operating'), + dataIndex: 'action', + fixed: false, + customRender: ({ record }) => { + const actions: ActionItem[] = [ + { + label: t('component.upload.del'), + color: 'error', + onClick: handleRemove.bind(null, record), + }, + ]; + return ; + }, + }; +} +// 文件预览列表 +export function createPreviewColumns(): BasicColumn[] { + return [ + { + dataIndex: 'url', + title: t('component.upload.legend'), + width: 100, + customRender: ({ record }) => { + const { url } = (record as PreviewFileItem) || {}; + return isImgTypeByName(url) && ; + }, + }, + { + dataIndex: 'name', + title: t('component.upload.fileName'), + align: 'left', + }, + ]; +} + +export function createPreviewActionColumn({ + handleRemove, + handleDownload, +}: { + handleRemove: Fn; + handleDownload: Fn; +}): BasicColumn { + return { + width: 160, + title: t('component.upload.operating'), + dataIndex: 'action', + fixed: false, + customRender: ({ record }) => { + const actions: ActionItem[] = [ + { + label: t('component.upload.del'), + color: 'error', + onClick: handleRemove.bind(null, record), + }, + { + label: t('component.upload.download'), + onClick: handleDownload.bind(null, record), + }, + ]; + + return ; + }, + }; +} diff --git a/src/components/Upload/src/components/image_preview.vue b/src/components/Upload/src/components/image_preview.vue new file mode 100644 index 0000000..aa2882d --- /dev/null +++ b/src/components/Upload/src/components/image_preview.vue @@ -0,0 +1,278 @@ + + + \ No newline at end of file diff --git a/src/components/Upload/src/components/img_pre.vue b/src/components/Upload/src/components/img_pre.vue new file mode 100644 index 0000000..42c80e8 --- /dev/null +++ b/src/components/Upload/src/components/img_pre.vue @@ -0,0 +1,145 @@ + + + \ No newline at end of file diff --git a/src/components/Upload/src/components/video.png b/src/components/Upload/src/components/video.png new file mode 100644 index 0000000..ba615a2 Binary files /dev/null and b/src/components/Upload/src/components/video.png differ diff --git a/src/components/Upload/src/helper.ts b/src/components/Upload/src/helper.ts new file mode 100644 index 0000000..cbc1425 --- /dev/null +++ b/src/components/Upload/src/helper.ts @@ -0,0 +1,32 @@ +export function checkFileType(file: File, accepts: string[]) { + const newTypes = accepts.join('|'); + // const reg = /\.(jpg|jpeg|png|gif|txt|doc|docx|xls|xlsx|xml)$/i; + const reg = new RegExp('\\.(' + newTypes + ')$', 'i'); + + return reg.test(file.name); +} + +export function checkImgType(file: File) { + return isImgTypeByName(file.name); +} + +export function isImgTypeByName(name: string) { + return /\.(jpg|jpeg|png|gif|webp)$/i.test(name); +} + + +export function isVideoTypeByName(name: string) { + return /\.(mp4|mov|avi)$/i.test(name); +} + +export function getBase64WithFile(file: File) { + return new Promise<{ + result: string; + file: File; + }>((resolve, reject) => { + const reader = new FileReader(); + reader.readAsDataURL(file); + reader.onload = () => resolve({ result: reader.result as string, file }); + reader.onerror = (error) => reject(error); + }); +} diff --git a/src/components/Upload/src/hooks/useUpload.ts b/src/components/Upload/src/hooks/useUpload.ts new file mode 100644 index 0000000..53fa380 --- /dev/null +++ b/src/components/Upload/src/hooks/useUpload.ts @@ -0,0 +1,61 @@ +import { Ref, unref, computed } from 'vue'; +import { useI18n } from '@/hooks/web/useI18n'; + +const { t } = useI18n(); +export function useUploadType({ + acceptRef, + helpTextRef, + maxNumberRef, + maxSizeRef, +}: { + acceptRef: Ref; + helpTextRef: Ref; + maxNumberRef: Ref; + maxSizeRef: Ref; +}) { + // 文件类型限制 + const getAccept = computed(() => { + const accept = unref(acceptRef); + if (accept && accept.length > 0) { + return accept; + } + return []; + }); + const getStringAccept = computed(() => { + return unref(getAccept) + .map((item) => { + if (item.indexOf('/') > 0 || item.startsWith('.')) { + return item; + } else { + return `.${item}`; + } + }) + .join(','); + }); + + // 支持jpg、jpeg、png格式,不超过2M,最多可选择10张图片,。 + const getHelpText = computed(() => { + const helpText = unref(helpTextRef); + if (helpText) { + return helpText; + } + const helpTexts: string[] = []; + + const accept = unref(acceptRef); + if (accept.length > 0) { + helpTexts.push(t('component.upload.accept', [accept.join(',')])); + } + + const maxSize = unref(maxSizeRef); + if (maxSize) { + helpTexts.push(t('component.upload.maxSize', [maxSize])); + } + + const maxNumber = unref(maxNumberRef); + if (maxNumber && maxNumber !== Infinity) { + helpTexts.push(t('component.upload.maxNumber', [maxNumber])); + } + return helpTexts.join(','); + }); + return { getAccept, getStringAccept, getHelpText }; +} diff --git a/src/components/Upload/src/props.ts b/src/components/Upload/src/props.ts new file mode 100644 index 0000000..9d077ef --- /dev/null +++ b/src/components/Upload/src/props.ts @@ -0,0 +1,129 @@ +import type { PropType } from 'vue'; +import { FileBasicColumn } from './types/typing'; + +import type { Options } from 'sortablejs'; + +import { Merge } from '@/utils/types'; + +type SortableOptions = Merge< + Omit, + { + onAfterEnd?: (params: T) => R; + // ...可扩展 + } +>; + +type ListType = 'text' | 'picture' | 'picture-card'; + +export const basicProps = { + listType: { + type: String as PropType, + default: 'picture-card', + }, + helpText: { + type: String as PropType, + default: '', + }, + action: { + type: String as PropType, + default: '', + }, + server: { + type: String as PropType, + default: '', + }, + azimuth: { + type: Boolean as PropType, + default: false, + }, + // 文件最大多少MB + maxSize: { + type: Number as PropType, + default: 50, + }, + // 最大数量的文件,Infinity不限制 + maxNumber: { + type: Number as PropType, + default: 1, + }, + // 根据后缀,或者其他 + accept: { + type: Array as PropType, + default: () => [], + }, + multiple: { + type: Boolean as PropType, + default: false, + }, + uploadParams: { + type: Object as PropType, + default: () => ({}), + }, + api: { + type: Function as PropType, + default: null, + required: true, + }, + name: { + type: String as PropType, + default: 'files', + }, + filename: { + type: String as PropType, + default: null, + }, + fileListOpenDrag: { + type: Boolean, + default: true, + }, + fileListDragOptions: { + type: Object as PropType, + default: () => ({}), + }, +}; + +export const uploadContainerProps = { + value: { + type: Array as PropType, + default: () => [], + }, + ...basicProps, + showPreviewNumber: { + type: Boolean as PropType, + default: true, + }, + emptyHidePreview: { + type: Boolean as PropType, + default: false, + }, +}; + +export const previewProps = { + value: { + type: Array as PropType, + default: () => [], + }, +}; + +export const fileListProps = { + columns: { + type: Array as PropType, + default: null, + }, + actionColumn: { + type: Object as PropType, + default: null, + }, + dataSource: { + type: Array as PropType, + default: null, + }, + openDrag: { + type: Boolean, + default: false, + }, + dragOptions: { + type: Object as PropType, + default: () => ({}), + }, +}; diff --git a/src/components/Upload/src/types/typing.ts b/src/components/Upload/src/types/typing.ts new file mode 100644 index 0000000..b87cdd6 --- /dev/null +++ b/src/components/Upload/src/types/typing.ts @@ -0,0 +1,46 @@ +import { BasicColumn } from '@/components/Table'; +import { UploadApiResult } from '@/api/sys/model/uploadModel'; + +export enum UploadResultStatus { + DONE = 'done', + SUCCESS = 'success', + ERROR = 'error', + UPLOADING = 'uploading', +} + +export interface FileItem { + thumbUrl?: string; + name: string; + size: string | number; + type?: string; + percent: number; + file: File; + status?: UploadResultStatus; + response?: UploadApiResult; + uuid: string; +} + +export interface PreviewFileItem { + url: string; + name: string; + type: string; +} + +export interface FileBasicColumn extends Omit { + /** + * Renderer of the table cell. The return value should be a VNode, or an object for colSpan/rowSpan config + * @type Function | ScopedSlot + */ + customRender?: Function; + /** + * Title of this column + * @type any (string | slot) + */ + title: string; + + /** + * Display field of the data record, could be set like a.b.c + * @type string + */ + dataIndex: string; +} diff --git a/src/components/Verify/index.ts b/src/components/Verify/index.ts new file mode 100644 index 0000000..13df25e --- /dev/null +++ b/src/components/Verify/index.ts @@ -0,0 +1,7 @@ +import { withInstall } from '@/utils'; +import basicDragVerify from './src/DragVerify.vue'; +import rotateDragVerify from './src/ImgRotate.vue'; + +export const BasicDragVerify = withInstall(basicDragVerify); +export const RotateDragVerify = withInstall(rotateDragVerify); +export * from './src/typing'; diff --git a/src/components/Verify/src/DragVerify.vue b/src/components/Verify/src/DragVerify.vue new file mode 100644 index 0000000..3b5dc04 --- /dev/null +++ b/src/components/Verify/src/DragVerify.vue @@ -0,0 +1,371 @@ + + diff --git a/src/components/Verify/src/ImgRotate.vue b/src/components/Verify/src/ImgRotate.vue new file mode 100644 index 0000000..9e6a4f9 --- /dev/null +++ b/src/components/Verify/src/ImgRotate.vue @@ -0,0 +1,220 @@ + + diff --git a/src/components/Verify/src/props.ts b/src/components/Verify/src/props.ts new file mode 100644 index 0000000..8805200 --- /dev/null +++ b/src/components/Verify/src/props.ts @@ -0,0 +1,87 @@ +import type { PropType } from 'vue'; +import { useI18n } from '@/hooks/web/useI18n'; + +const { t } = useI18n(); +export const basicProps = { + value: { + type: Boolean as PropType, + default: false, + }, + + isSlot: { + type: Boolean as PropType, + default: false, + }, + + text: { + type: [String] as PropType, + default: t('component.verify.dragText'), + }, + successText: { + type: [String] as PropType, + default: t('component.verify.successText'), + }, + height: { + type: [Number, String] as PropType, + default: 40, + }, + + width: { + type: [Number, String] as PropType, + default: 220, + }, + + circle: { + type: Boolean as PropType, + default: false, + }, + + wrapStyle: { + type: Object as PropType, + default: () => ({}), + }, + contentStyle: { + type: Object as PropType, + default: () => ({}), + }, + barStyle: { + type: Object as PropType, + default: () => ({}), + }, + actionStyle: { + type: Object as PropType, + default: () => ({}), + }, +}; + +export const rotateProps = { + ...basicProps, + src: { + type: String as PropType, + }, + + imgWidth: { + type: Number as PropType, + default: 260, + }, + + imgWrapStyle: { + type: Object as PropType, + default: () => ({}), + }, + + minDegree: { + type: Number as PropType, + default: 90, + }, + + maxDegree: { + type: Number as PropType, + default: 270, + }, + + diffDegree: { + type: Number as PropType, + default: 20, + }, +}; diff --git a/src/components/Verify/src/typing.ts b/src/components/Verify/src/typing.ts new file mode 100644 index 0000000..48f7d4c --- /dev/null +++ b/src/components/Verify/src/typing.ts @@ -0,0 +1,14 @@ +export interface DragVerifyActionType { + resume: () => void; +} + +export interface PassingData { + isPassing: boolean; + time: number; +} + +export interface MoveData { + event: MouseEvent | TouchEvent; + moveDistance: number; + moveX: number; +} diff --git a/src/components/VirtualScroll/index.ts b/src/components/VirtualScroll/index.ts new file mode 100644 index 0000000..719abae --- /dev/null +++ b/src/components/VirtualScroll/index.ts @@ -0,0 +1,4 @@ +import { withInstall } from '@/utils'; +import vScroll from './src/VirtualScroll.vue'; + +export const VScroll = withInstall(vScroll); diff --git a/src/components/VirtualScroll/src/VirtualScroll.vue b/src/components/VirtualScroll/src/VirtualScroll.vue new file mode 100644 index 0000000..2551003 --- /dev/null +++ b/src/components/VirtualScroll/src/VirtualScroll.vue @@ -0,0 +1,191 @@ + + diff --git a/src/components/VxeTable/index.ts b/src/components/VxeTable/index.ts new file mode 100644 index 0000000..be12129 --- /dev/null +++ b/src/components/VxeTable/index.ts @@ -0,0 +1,12 @@ +import { withInstall } from '@/utils'; +import vxeBasicTable from './src/VxeBasicTable'; +import { VXETable } from 'vxe-table'; +import VXETablePluginAntd from './src/components'; +import VXETablePluginExportXLSX from 'vxe-table-plugin-export-xlsx'; +import './src/setting'; + +export const VxeBasicTable = withInstall(vxeBasicTable); +export * from 'vxe-table'; +export * from './src/types'; + +VXETable.use(VXETablePluginAntd).use(VXETablePluginExportXLSX); diff --git a/src/components/VxeTable/src/VxeBasicTable.tsx b/src/components/VxeTable/src/VxeBasicTable.tsx new file mode 100644 index 0000000..e48cb10 --- /dev/null +++ b/src/components/VxeTable/src/VxeBasicTable.tsx @@ -0,0 +1,116 @@ +import { defineComponent, computed, ref } from 'vue'; +import { BasicTableProps } from './types'; +import { basicProps } from './props'; +import { ignorePropKeys } from './const'; +import { basicEmits } from './emits'; +import XEUtils from 'xe-utils'; +import type { + VxeGridInstance, + VxeGridEventProps, + GridMethods, + TableMethods, + TableEditMethods, + TableValidatorMethods, +} from 'vxe-table'; +import { Grid as VxeGrid } from 'vxe-table'; + +import { extendSlots } from '@/utils/helper/tsxHelper'; +import { gridComponentMethodKeys } from './methods'; +import { omit } from 'lodash-es'; + +export default defineComponent({ + name: 'VxeBasicTable', + props: basicProps, + emits: basicEmits, + setup(props, { emit, attrs }) { + const tableElRef = ref(); + const emitEvents: VxeGridEventProps = {}; + + const extendTableMethods = (methodKeys) => { + const funcs: any = {}; + methodKeys.forEach((name) => { + funcs[name] = (...args: any[]) => { + const $vxegrid: any = tableElRef.value; + if ($vxegrid && $vxegrid[name]) { + return $vxegrid[name](...args); + } + }; + }); + + return funcs; + }; + + const gridExtendTableMethods = extendTableMethods(gridComponentMethodKeys) as GridMethods & + TableMethods & + TableEditMethods & + TableValidatorMethods; + + basicEmits.forEach((name) => { + const type = XEUtils.camelCase(`on-${name}`) as keyof VxeGridEventProps; + + emitEvents[type] = (...args: any[]) => emit(name, ...args); + }); + + /** + * @description: 二次封装需要的所有属性 + * 1.部分属性需要和全局属性进行合并 + */ + const getBindValues = computed(() => { + const propsData: BasicTableProps = { + ...attrs, + ...props, + }; + + return propsData; + }); + + /** + * @description: Table 所有属性 + */ + const getBindGridValues = computed(() => { + const omitProps = omit(getBindValues.value, ignorePropKeys); + + return { + ...omitProps, + ...getBindGridEvent, + }; + }); + + /** + * @description: 组件外层class + */ + const getWrapperClass = computed(() => { + return [attrs.class]; + }); + + /** + * @description: 重写Vxe-table 方法 + */ + const getBindGridEvent: VxeGridEventProps = { + ...emitEvents, + }; + + return { + getWrapperClass, + getBindGridValues, + tableElRef, + ...gridExtendTableMethods, + }; + }, + render() { + const { tableClass, tableStyle } = this.$props; + + return ( +
+ + {extendSlots(this.$slots)} + +
+ ); + }, +}); diff --git a/src/components/VxeTable/src/componentMap.ts b/src/components/VxeTable/src/componentMap.ts new file mode 100644 index 0000000..04a632e --- /dev/null +++ b/src/components/VxeTable/src/componentMap.ts @@ -0,0 +1,59 @@ +import type { Component } from 'vue'; + +import type { ComponentType } from './componentType'; +import { ApiSelect, ApiTreeSelect } from '@/components/Form'; +import { + Input, + Select, + Radio, + Checkbox, + AutoComplete, + Cascader, + DatePicker, + InputNumber, + Switch, + TimePicker, + TreeSelect, + Rate, + Empty, +} from 'ant-design-vue'; +import { Button } from '@/components/Button'; + +const componentMap = new Map(); + +componentMap.set('AButton', Button); + +componentMap.set('AInput', Input); +componentMap.set('AInputSearch', Input.Search); +componentMap.set('AInputNumber', InputNumber); +componentMap.set('AAutoComplete', AutoComplete); + +componentMap.set('ASelect', Select); +componentMap.set('ATreeSelect', TreeSelect); +componentMap.set('ASwitch', Switch); +componentMap.set('ARadioGroup', Radio.Group); +componentMap.set('ACheckboxGroup', Checkbox.Group); +componentMap.set('ACascader', Cascader); +componentMap.set('ARate', Rate); + +componentMap.set('ADatePicker', DatePicker); +componentMap.set('AMonthPicker', DatePicker.MonthPicker); +componentMap.set('ARangePicker', DatePicker.RangePicker); +componentMap.set('AWeekPicker', DatePicker.WeekPicker); +componentMap.set('AYearPicker', DatePicker.YearPicker); +componentMap.set('ATimePicker', TimePicker); + +componentMap.set('AApiSelect', ApiSelect); +componentMap.set('AApiTreeSelect', ApiTreeSelect); + +componentMap.set('AEmpty', Empty); + +export function add(compName: ComponentType, component: Component) { + componentMap.set(compName, component); +} + +export function del(compName: ComponentType) { + componentMap.delete(compName); +} + +export { componentMap }; diff --git a/src/components/VxeTable/src/componentType.ts b/src/components/VxeTable/src/componentType.ts new file mode 100644 index 0000000..4a55e64 --- /dev/null +++ b/src/components/VxeTable/src/componentType.ts @@ -0,0 +1,22 @@ +export type ComponentType = + | 'AInput' + | 'AInputNumber' + | 'ASelect' + | 'AApiSelect' + | 'ATreeSelect' + | 'AApiTreeSelect' + | 'ARadioGroup' + | 'ACheckboxGroup' + | 'AAutoComplete' + | 'ACascader' + | 'ADatePicker' + | 'AMonthPicker' + | 'ARangePicker' + | 'AWeekPicker' + | 'ATimePicker' + | 'AYearPicker' + | 'ASwitch' + | 'ARate' + | 'AInputSearch' + | 'AButton' + | 'AEmpty'; diff --git a/src/components/VxeTable/src/components/AApiSelect.tsx b/src/components/VxeTable/src/components/AApiSelect.tsx new file mode 100644 index 0000000..8fb1d3d --- /dev/null +++ b/src/components/VxeTable/src/components/AApiSelect.tsx @@ -0,0 +1,20 @@ +import XEUtils from 'xe-utils'; +import { createDefaultRender, createEditRender, createFormItemRender } from './common'; + +export default { + renderDefault: createDefaultRender({}, (_, params) => { + return { + params: XEUtils.get(params, 'row'), + }; + }), + renderEdit: createEditRender({}, (_, params) => { + return { + params: XEUtils.get(params, 'row'), + }; + }), + renderItemContent: createFormItemRender({}, (_, params) => { + return { + params: XEUtils.get(params, 'row'), + }; + }), +}; diff --git a/src/components/VxeTable/src/components/AApiTreeSelect.tsx b/src/components/VxeTable/src/components/AApiTreeSelect.tsx new file mode 100644 index 0000000..8fb1d3d --- /dev/null +++ b/src/components/VxeTable/src/components/AApiTreeSelect.tsx @@ -0,0 +1,20 @@ +import XEUtils from 'xe-utils'; +import { createDefaultRender, createEditRender, createFormItemRender } from './common'; + +export default { + renderDefault: createDefaultRender({}, (_, params) => { + return { + params: XEUtils.get(params, 'row'), + }; + }), + renderEdit: createEditRender({}, (_, params) => { + return { + params: XEUtils.get(params, 'row'), + }; + }), + renderItemContent: createFormItemRender({}, (_, params) => { + return { + params: XEUtils.get(params, 'row'), + }; + }), +}; diff --git a/src/components/VxeTable/src/components/AAutoComplete.tsx b/src/components/VxeTable/src/components/AAutoComplete.tsx new file mode 100644 index 0000000..41ca4a4 --- /dev/null +++ b/src/components/VxeTable/src/components/AAutoComplete.tsx @@ -0,0 +1,16 @@ +import { + createEditRender, + createDefaultRender, + createFilterRender, + createDefaultFilterRender, + createFormItemRender, +} from './common'; + +export default { + autofocus: 'input.ant-input', + renderDefault: createDefaultRender(), + renderEdit: createEditRender(), + renderFilter: createFilterRender(), + defaultFilterMethod: createDefaultFilterRender(), + renderItemContent: createFormItemRender(), +}; diff --git a/src/components/VxeTable/src/components/AButton.tsx b/src/components/VxeTable/src/components/AButton.tsx new file mode 100644 index 0000000..67468d1 --- /dev/null +++ b/src/components/VxeTable/src/components/AButton.tsx @@ -0,0 +1,120 @@ +import { h } from 'vue'; +import { + FormItemContentRenderParams, + FormItemRenderOptions, + VxeGlobalRendererHandles, +} from 'vxe-table'; +import XEUtils from 'xe-utils'; +import { cellText, createEvents, createProps, getComponent } from './common'; + +const COMPONENT_NAME = 'AButton'; + +export function createEditRender() { + return function ( + renderOpts: VxeGlobalRendererHandles.RenderEditOptions, + params: VxeGlobalRendererHandles.RenderEditParams, + ) { + const { attrs } = renderOpts; + const Component = getComponent(COMPONENT_NAME); + + return [ + h(Component, { + ...attrs, + ...createProps(renderOpts, null), + ...createEvents(renderOpts, params), + }), + ]; + }; +} + +export function createDefaultRender() { + return function ( + renderOpts: VxeGlobalRendererHandles.RenderEditOptions, + params: VxeGlobalRendererHandles.RenderEditParams, + ) { + const { attrs } = renderOpts; + const Component = getComponent(COMPONENT_NAME); + + return [ + h( + Component, + { + ...attrs, + ...createProps(renderOpts, null), + ...createEvents(renderOpts, params), + }, + cellText(renderOpts.content), + ), + ]; + }; +} + +export function createFormItemRender() { + return function (renderOpts: FormItemRenderOptions, params: FormItemContentRenderParams) { + const { attrs, content } = renderOpts; + const { property, $form, data } = params; + const props = createProps(renderOpts, null); + const Component = getComponent(COMPONENT_NAME); + + return [ + h( + Component, + { + ...attrs, + ...props, + ...createEvents( + renderOpts, + params, + (value: any) => { + // 处理 model 值双向绑定 + XEUtils.set(data, property, value); + }, + () => { + // 处理 change 事件相关逻辑 + $form.updateStatus({ + ...params, + field: property, + }); + }, + ), + }, + { + default: () => cellText(content || props.content), + }, + ), + ]; + }; +} + +function createToolbarButtonRender() { + return function ( + renderOpts: VxeGlobalRendererHandles.RenderToolOptions, + params: VxeGlobalRendererHandles.RenderButtonParams, + ) { + const { attrs } = renderOpts; + const { button } = params; + const props = createProps(renderOpts, null); + const Component = getComponent(COMPONENT_NAME); + + return [ + h( + Component, + { + ...attrs, + ...props, + ...createEvents(renderOpts, params), + }, + { + default: () => cellText(button?.content || props.content), + }, + ), + ]; + }; +} + +export default { + renderEdit: createEditRender(), + renderDefault: createDefaultRender(), + renderItemContent: createFormItemRender(), + renderToolbarButton: createToolbarButtonRender(), +}; diff --git a/src/components/VxeTable/src/components/AButtonGroup.tsx b/src/components/VxeTable/src/components/AButtonGroup.tsx new file mode 100644 index 0000000..ed0fc84 --- /dev/null +++ b/src/components/VxeTable/src/components/AButtonGroup.tsx @@ -0,0 +1,59 @@ +import { + FormItemContentRenderParams, + FormItemRenderOptions, + VxeGlobalRendererHandles, +} from 'vxe-table'; +import { createDefaultRender, createEditRender, createFormItemRender } from './AButton'; + +function createEditButtonRender() { + return function ( + renderOpts: VxeGlobalRendererHandles.RenderEditOptions, + params: VxeGlobalRendererHandles.RenderEditParams, + ) { + const buttonEditRender = createEditRender(); + const { children } = renderOpts; + if (children) { + return children.map( + (childRenderOpts: VxeGlobalRendererHandles.RenderEditOptions) => + buttonEditRender(childRenderOpts, params)[0], + ); + } + return []; + }; +} + +function createDefaultButtonRender() { + return function ( + renderOpts: VxeGlobalRendererHandles.RenderDefaultOptions, + params: VxeGlobalRendererHandles.RenderDefaultParams, + ) { + const buttonDefaultRender = createDefaultRender(); + const { children } = renderOpts; + if (children) { + return children.map( + (childRenderOpts: VxeGlobalRendererHandles.RenderDefaultOptions) => + buttonDefaultRender(childRenderOpts, params)[0], + ); + } + return []; + }; +} + +function createButtonItemRender() { + return function (renderOpts: FormItemRenderOptions, params: FormItemContentRenderParams) { + const buttonItemRender = createFormItemRender(); + const { children } = renderOpts; + if (children) { + return children.map( + (childRenderOpts: FormItemRenderOptions) => buttonItemRender(childRenderOpts, params)[0], + ); + } + return []; + }; +} + +export default { + renderEdit: createEditButtonRender(), + renderDefault: createDefaultButtonRender(), + renderItemContent: createButtonItemRender(), +}; diff --git a/src/components/VxeTable/src/components/ACascader.tsx b/src/components/VxeTable/src/components/ACascader.tsx new file mode 100644 index 0000000..650f32f --- /dev/null +++ b/src/components/VxeTable/src/components/ACascader.tsx @@ -0,0 +1,42 @@ +import { VxeGlobalRendererHandles } from 'vxe-table'; +import XEUtils from 'xe-utils'; +import { + createEditRender, + createCellRender, + createFormItemRender, + createExportMethod, +} from './common'; + +function matchCascaderData(index: number, list: any[], values: any[], labels: any[]) { + const val = values[index]; + if (list && values.length > index) { + XEUtils.each(list, (item) => { + if (item.value === val) { + labels.push(item.label); + matchCascaderData(++index, item.children, values, labels); + } + }); + } +} + +function getCascaderCellValue( + renderOpts: VxeGlobalRendererHandles.RenderOptions, + params: VxeGlobalRendererHandles.RenderCellParams, +) { + const { props = {} } = renderOpts; + const { row, column } = params; + const cellValue = XEUtils.get(row, column.field as string); + const values = cellValue || []; + const labels: Array = []; + matchCascaderData(0, props.options, values, labels); + return ( + props.showAllLevels === false ? labels.slice(labels.length - 1, labels.length) : labels + ).join(` ${props.separator || '/'} `); +} + +export default { + renderEdit: createEditRender(), + renderCell: createCellRender(getCascaderCellValue), + renderItemContent: createFormItemRender(), + exportMethod: createExportMethod(getCascaderCellValue), +}; diff --git a/src/components/VxeTable/src/components/ACheckboxGroup.tsx b/src/components/VxeTable/src/components/ACheckboxGroup.tsx new file mode 100644 index 0000000..d01092a --- /dev/null +++ b/src/components/VxeTable/src/components/ACheckboxGroup.tsx @@ -0,0 +1,5 @@ +import { createFormItemRender } from './common'; + +export default { + renderItemContent: createFormItemRender(), +}; diff --git a/src/components/VxeTable/src/components/ADatePicker.tsx b/src/components/VxeTable/src/components/ADatePicker.tsx new file mode 100644 index 0000000..3e90638 --- /dev/null +++ b/src/components/VxeTable/src/components/ADatePicker.tsx @@ -0,0 +1,33 @@ +import { VxeGlobalRendererHandles } from 'vxe-table'; +import XEUtils from 'xe-utils'; +import { + createCellRender, + createEditRender, + createExportMethod, + createFormItemRender, +} from './common'; + +export function getDatePickerCellValue( + renderOpts: VxeGlobalRendererHandles.RenderOptions, + params: VxeGlobalRendererHandles.RenderCellParams | VxeGlobalRendererHandles.ExportMethodParams, + defaultFormat: string, +) { + const { props = {} } = renderOpts; + const { row, column } = params; + let cellValue = XEUtils.get(row, column.field as string); + if (cellValue) { + cellValue = cellValue.format(props.format || defaultFormat); + } + return cellValue; +} + +export default { + renderEdit: createEditRender(), + renderCell: createCellRender(getDatePickerCellValue, () => { + return ['YYYY-MM-DD']; + }), + renderItemContent: createFormItemRender(), + exportMethod: createExportMethod(getDatePickerCellValue, () => { + return ['YYYY-MM-DD']; + }), +}; diff --git a/src/components/VxeTable/src/components/AEmpty.tsx b/src/components/VxeTable/src/components/AEmpty.tsx new file mode 100644 index 0000000..aed5007 --- /dev/null +++ b/src/components/VxeTable/src/components/AEmpty.tsx @@ -0,0 +1,27 @@ +import { h } from 'vue'; +import { VxeGlobalRendererHandles } from 'vxe-table'; +import { getComponent } from './common'; + +function createEmptyRender() { + return function (renderOpts: VxeGlobalRendererHandles.RenderEmptyOptions) { + const { name, attrs, props } = renderOpts; + + const Component = getComponent(name); + return [ + h( + 'div', + { + class: 'flex items-center justify-center', + }, + h(Component, { + ...attrs, + ...props, + }), + ), + ]; + }; +} + +export default { + renderEmpty: createEmptyRender(), +}; diff --git a/src/components/VxeTable/src/components/AInput.tsx b/src/components/VxeTable/src/components/AInput.tsx new file mode 100644 index 0000000..41ca4a4 --- /dev/null +++ b/src/components/VxeTable/src/components/AInput.tsx @@ -0,0 +1,16 @@ +import { + createEditRender, + createDefaultRender, + createFilterRender, + createDefaultFilterRender, + createFormItemRender, +} from './common'; + +export default { + autofocus: 'input.ant-input', + renderDefault: createDefaultRender(), + renderEdit: createEditRender(), + renderFilter: createFilterRender(), + defaultFilterMethod: createDefaultFilterRender(), + renderItemContent: createFormItemRender(), +}; diff --git a/src/components/VxeTable/src/components/AInputNumber.tsx b/src/components/VxeTable/src/components/AInputNumber.tsx new file mode 100644 index 0000000..22f299e --- /dev/null +++ b/src/components/VxeTable/src/components/AInputNumber.tsx @@ -0,0 +1,16 @@ +import { + createEditRender, + createFilterRender, + createFormItemRender, + createDefaultFilterRender, + createDefaultRender, +} from './common'; + +export default { + autofocus: 'input.ant-input-number-input', + renderDefault: createDefaultRender(), + renderEdit: createEditRender(), + renderFilter: createFilterRender(), + defaultFilterMethod: createDefaultFilterRender(), + renderItemContent: createFormItemRender(), +}; diff --git a/src/components/VxeTable/src/components/AInputSearch.tsx b/src/components/VxeTable/src/components/AInputSearch.tsx new file mode 100644 index 0000000..e365ef3 --- /dev/null +++ b/src/components/VxeTable/src/components/AInputSearch.tsx @@ -0,0 +1,17 @@ +import { + createEditRender, + createDefaultRender, + createFilterRender, + createDefaultFilterRender, + createFormItemRender, + createToolbarToolRender, +} from './common'; + +export default { + renderDefault: createDefaultRender(), + renderEdit: createEditRender(), + renderFilter: createFilterRender(), + defaultFilterMethod: createDefaultFilterRender(), + renderItemContent: createFormItemRender(), + renderToolbarTool: createToolbarToolRender(), +}; diff --git a/src/components/VxeTable/src/components/AMonthPicker.tsx b/src/components/VxeTable/src/components/AMonthPicker.tsx new file mode 100644 index 0000000..f46bbae --- /dev/null +++ b/src/components/VxeTable/src/components/AMonthPicker.tsx @@ -0,0 +1,18 @@ +import { getDatePickerCellValue } from './ADatePicker'; +import { + createCellRender, + createEditRender, + createExportMethod, + createFormItemRender, +} from './common'; + +export default { + renderEdit: createEditRender(), + renderCell: createCellRender(getDatePickerCellValue, () => { + return ['YYYY-MM']; + }), + renderItemContent: createFormItemRender(), + exportMethod: createExportMethod(getDatePickerCellValue, () => { + return ['YYYY-MM']; + }), +}; diff --git a/src/components/VxeTable/src/components/ARadioGroup.tsx b/src/components/VxeTable/src/components/ARadioGroup.tsx new file mode 100644 index 0000000..d01092a --- /dev/null +++ b/src/components/VxeTable/src/components/ARadioGroup.tsx @@ -0,0 +1,5 @@ +import { createFormItemRender } from './common'; + +export default { + renderItemContent: createFormItemRender(), +}; diff --git a/src/components/VxeTable/src/components/ARangePicker.tsx b/src/components/VxeTable/src/components/ARangePicker.tsx new file mode 100644 index 0000000..ce0da2c --- /dev/null +++ b/src/components/VxeTable/src/components/ARangePicker.tsx @@ -0,0 +1,30 @@ +import { VxeColumnPropTypes, VxeGlobalRendererHandles } from 'vxe-table'; +import XEUtils from 'xe-utils'; +import { + createCellRender, + createEditRender, + createExportMethod, + createFormItemRender, +} from './common'; + +function getRangePickerCellValue( + renderOpts: VxeColumnPropTypes.EditRender, + params: VxeGlobalRendererHandles.RenderCellParams | VxeGlobalRendererHandles.ExportMethodParams, +) { + const { props = {} } = renderOpts; + const { row, column } = params; + let cellValue = XEUtils.get(row, column.field as string); + if (cellValue) { + cellValue = XEUtils.map(cellValue, (date: any) => + date.format(props.format || 'YYYY-MM-DD'), + ).join(' ~ '); + } + return cellValue; +} + +export default { + renderEdit: createEditRender(), + renderCell: createCellRender(getRangePickerCellValue), + renderItemContent: createFormItemRender(), + exportMethod: createExportMethod(getRangePickerCellValue), +}; diff --git a/src/components/VxeTable/src/components/ARate.tsx b/src/components/VxeTable/src/components/ARate.tsx new file mode 100644 index 0000000..3ec3f6b --- /dev/null +++ b/src/components/VxeTable/src/components/ARate.tsx @@ -0,0 +1,15 @@ +import { + createEditRender, + createDefaultRender, + createFilterRender, + createDefaultFilterRender, + createFormItemRender, +} from './common'; + +export default { + renderDefault: createDefaultRender(), + renderEdit: createEditRender(), + renderFilter: createFilterRender(), + defaultFilterMethod: createDefaultFilterRender(), + renderItemContent: createFormItemRender(), +}; diff --git a/src/components/VxeTable/src/components/ASelect.tsx b/src/components/VxeTable/src/components/ASelect.tsx new file mode 100644 index 0000000..2785fe7 --- /dev/null +++ b/src/components/VxeTable/src/components/ASelect.tsx @@ -0,0 +1,271 @@ +import { ComponentOptions, h, resolveComponent } from 'vue'; +import { VxeColumnPropTypes, VxeGlobalRendererHandles } from 'vxe-table'; +import XEUtils from 'xe-utils'; +import { + cellText, + createCellRender, + createEvents, + createProps, + isEmptyValue, + createExportMethod, + createFormItemRender, +} from './common'; + +function renderOptions(options: any[], optionProps: VxeGlobalRendererHandles.RenderOptionProps) { + const labelProp = optionProps.label || 'label'; + const valueProp = optionProps.value || 'value'; + return XEUtils.map(options, (item, oIndex) => { + return h( + resolveComponent('a-select-option') as ComponentOptions, + { + key: oIndex, + value: item[valueProp], + disabled: item.disabled, + }, + { + default: () => cellText(item[labelProp]), + }, + ); + }); +} + +function createEditRender() { + return function ( + renderOpts: VxeColumnPropTypes.EditRender, + params: VxeGlobalRendererHandles.RenderEditParams, + ) { + const { options = [], optionGroups, optionProps = {}, optionGroupProps = {} } = renderOpts; + const { row, column, $table } = params; + const { attrs } = renderOpts; + const cellValue = XEUtils.get(row, column.field as string); + const props = createProps(renderOpts, cellValue); + const ons = createEvents( + renderOpts, + params, + (value: any) => { + // 处理 model 值双向绑定 + XEUtils.set(row, column.field as string, value); + }, + () => { + // 处理 change 事件相关逻辑 + $table.updateStatus(params); + }, + ); + if (optionGroups) { + const groupOptions = optionGroupProps.options || 'options'; + const groupLabel = optionGroupProps.label || 'label'; + return [ + h( + resolveComponent('a-select') as ComponentOptions, + { + ...attrs, + ...props, + ...ons, + }, + { + default: () => { + return XEUtils.map(optionGroups, (group, gIndex) => { + return h( + resolveComponent('a-select-opt-group') as ComponentOptions, + { + key: gIndex, + }, + { + label: () => { + return h('span', {}, group[groupLabel]); + }, + default: () => renderOptions(group[groupOptions], optionProps), + }, + ); + }); + }, + }, + ), + ]; + } + return [ + h( + resolveComponent('a-select') as ComponentOptions, + { + ...props, + ...attrs, + ...ons, + }, + { + default: () => renderOptions(options, optionProps), + }, + ), + ]; + }; +} + +function getSelectCellValue( + renderOpts: VxeGlobalRendererHandles.RenderCellOptions, + params: VxeGlobalRendererHandles.RenderCellParams, +) { + const { + options = [], + optionGroups, + props = {}, + optionProps = {}, + optionGroupProps = {}, + } = renderOpts; + const { row, column } = params; + const labelProp = optionProps.label || 'label'; + const valueProp = optionProps.value || 'value'; + const groupOptions = optionGroupProps.options || 'options'; + const cellValue = XEUtils.get(row, column.field as string); + if (!isEmptyValue(cellValue)) { + return XEUtils.map( + props.mode === 'multiple' ? cellValue : [cellValue], + optionGroups + ? (value) => { + let selectItem; + for (let index = 0; index < optionGroups.length; index++) { + selectItem = XEUtils.find( + optionGroups[index][groupOptions], + (item) => item[valueProp] === value, + ); + if (selectItem) { + break; + } + } + return selectItem ? selectItem[labelProp] : value; + } + : (value) => { + const selectItem = XEUtils.find(options, (item) => item[valueProp] === value); + return selectItem ? selectItem[labelProp] : value; + }, + ).join(', '); + } + return ''; +} + +function createFilterRender() { + return function ( + renderOpts: VxeColumnPropTypes.FilterRender, + params: VxeGlobalRendererHandles.RenderFilterParams, + ) { + const { options = [], optionGroups, optionProps = {}, optionGroupProps = {} } = renderOpts; + const groupOptions = optionGroupProps.options || 'options'; + const groupLabel = optionGroupProps.label || 'label'; + const { column } = params; + const { attrs } = renderOpts; + + return [ + h( + 'div', + { + class: 'vxe-table--filter-antd-wrapper', + }, + optionGroups + ? column.filters.map((option, oIndex) => { + const optionValue = option.data; + const props = createProps(renderOpts, optionValue); + + return h( + resolveComponent('a-select') as ComponentOptions, + { + key: oIndex, + ...attrs, + ...props, + ...createEvents( + renderOpts, + params, + (value: any) => { + // 处理 model 值双向绑定 + option.data = value; + }, + () => { + // 处理 change 事件相关逻辑 + const { $panel } = params; + $panel.changeOption( + null, + props.mode === 'multiple' + ? option.data && option.data.length > 0 + : !XEUtils.eqNull(option.data), + option, + ); + }, + ), + }, + { + default: () => { + return XEUtils.map(optionGroups, (group, gIndex) => { + return h( + resolveComponent('a-select-opt-group') as ComponentOptions, + { + key: gIndex, + }, + { + label: () => { + return h('span', {}, group[groupLabel]); + }, + default: () => renderOptions(group[groupOptions], optionProps), + }, + ); + }); + }, + }, + ); + }) + : column.filters.map((option, oIndex) => { + const optionValue = option.data; + const props = createProps(renderOpts, optionValue); + return h( + resolveComponent('a-select') as ComponentOptions, + { + key: oIndex, + ...attrs, + ...props, + ...createEvents( + renderOpts, + params, + (value: any) => { + // 处理 model 值双向绑定 + option.data = value; + }, + () => { + // 处理 change 事件相关逻辑 + const { $panel } = params; + $panel.changeOption( + null, + props.mode === 'multiple' + ? option.data && option.data.length > 0 + : !XEUtils.eqNull(option.data), + option, + ); + }, + ), + }, + { + default: () => renderOptions(options, optionProps), + }, + ); + }), + ), + ]; + }; +} + +export default { + renderEdit: createEditRender(), + renderCell: createCellRender(getSelectCellValue), + renderFilter: createFilterRender(), + defaultFilterMethod(params) { + const { option, row, column } = params; + const { data } = option; + const { field, filterRender: renderOpts } = column; + const { props = {} } = renderOpts; + const cellValue = XEUtils.get(row, field); + if (props.mode === 'multiple') { + if (XEUtils.isArray(cellValue)) { + return XEUtils.includeArrays(cellValue, data); + } + return data.indexOf(cellValue) > -1; + } + return cellValue == data; + }, + renderItemContent: createFormItemRender(), + exportMethod: createExportMethod(getSelectCellValue), +}; diff --git a/src/components/VxeTable/src/components/ASwitch.tsx b/src/components/VxeTable/src/components/ASwitch.tsx new file mode 100644 index 0000000..634ab7f --- /dev/null +++ b/src/components/VxeTable/src/components/ASwitch.tsx @@ -0,0 +1,53 @@ +import { h } from 'vue'; +import XEUtils from 'xe-utils'; +import { + createEditRender, + createDefaultRender, + createProps, + createEvents, + createDefaultFilterRender, + createFormItemRender, + getComponent, +} from './common'; + +export default { + renderDefault: createDefaultRender(), + renderEdit: createEditRender(), + renderFilter(renderOpts, params) { + const { column } = params; + const { name, attrs } = renderOpts; + const Component = getComponent(name); + + return [ + h( + 'div', + { + class: 'vxe-table--filter-antd-wrapper', + }, + column.filters.map((option, oIndex) => { + const optionValue = option.data; + return h(Component, { + key: oIndex, + ...attrs, + ...createProps(renderOpts, optionValue), + ...createEvents( + renderOpts, + params, + (value: any) => { + // 处理 model 值双向绑定 + option.data = value; + }, + () => { + // 处理 change 事件相关逻辑 + const { $panel } = params; + $panel.changeOption(null, XEUtils.isBoolean(option.data), option); + }, + ), + }); + }), + ), + ]; + }, + defaultFilterMethod: createDefaultFilterRender(), + renderItemContent: createFormItemRender(), +}; diff --git a/src/components/VxeTable/src/components/ATimePicker.tsx b/src/components/VxeTable/src/components/ATimePicker.tsx new file mode 100644 index 0000000..7d2be54 --- /dev/null +++ b/src/components/VxeTable/src/components/ATimePicker.tsx @@ -0,0 +1,18 @@ +import { getDatePickerCellValue } from './ADatePicker'; +import { + createEditRender, + createCellRender, + createFormItemRender, + createExportMethod, +} from './common'; + +export default { + renderEdit: createEditRender(), + renderCell: createCellRender(getDatePickerCellValue, () => { + return ['HH:mm:ss']; + }), + renderItemContent: createFormItemRender(), + exportMethod: createExportMethod(getDatePickerCellValue, () => { + return ['HH:mm:ss']; + }), +}; diff --git a/src/components/VxeTable/src/components/ATreeSelect.tsx b/src/components/VxeTable/src/components/ATreeSelect.tsx new file mode 100644 index 0000000..5cb577a --- /dev/null +++ b/src/components/VxeTable/src/components/ATreeSelect.tsx @@ -0,0 +1,35 @@ +import { VxeGlobalRendererHandles } from 'vxe-table'; +import XEUtils from 'xe-utils'; +import { + createEditRender, + createCellRender, + isEmptyValue, + createFormItemRender, + createExportMethod, +} from './common'; + +function getTreeSelectCellValue( + renderOpts: VxeGlobalRendererHandles.RenderOptions, + params: VxeGlobalRendererHandles.RenderCellParams | VxeGlobalRendererHandles.ExportMethodParams, +) { + const { props = {} } = renderOpts; + const { treeData, treeCheckable } = props; + const { row, column } = params; + const cellValue = XEUtils.get(row, column.field as string); + if (!isEmptyValue(cellValue)) { + return XEUtils.map(treeCheckable ? cellValue : [cellValue], (value) => { + const matchObj = XEUtils.findTree(treeData, (item: any) => item.value === value, { + children: 'children', + }); + return matchObj ? matchObj.item.title : value; + }).join(', '); + } + return cellValue; +} + +export default { + renderEdit: createEditRender(), + renderCell: createCellRender(getTreeSelectCellValue), + renderItemContent: createFormItemRender(), + exportMethod: createExportMethod(getTreeSelectCellValue), +}; diff --git a/src/components/VxeTable/src/components/AWeekPicker.tsx b/src/components/VxeTable/src/components/AWeekPicker.tsx new file mode 100644 index 0000000..97b34e5 --- /dev/null +++ b/src/components/VxeTable/src/components/AWeekPicker.tsx @@ -0,0 +1,18 @@ +import { getDatePickerCellValue } from './ADatePicker'; +import { + createEditRender, + createCellRender, + createFormItemRender, + createExportMethod, +} from './common'; + +export default { + renderEdit: createEditRender(), + renderCell: createCellRender(getDatePickerCellValue, () => { + return ['YYYY-WW周']; + }), + renderItemContent: createFormItemRender(), + exportMethod: createExportMethod(getDatePickerCellValue, () => { + return ['YYYY-WW周']; + }), +}; diff --git a/src/components/VxeTable/src/components/AYearPicker.tsx b/src/components/VxeTable/src/components/AYearPicker.tsx new file mode 100644 index 0000000..6e73c19 --- /dev/null +++ b/src/components/VxeTable/src/components/AYearPicker.tsx @@ -0,0 +1,18 @@ +import { getDatePickerCellValue } from './ADatePicker'; +import { + createEditRender, + createCellRender, + createFormItemRender, + createExportMethod, +} from './common'; + +export default { + renderEdit: createEditRender(), + renderCell: createCellRender(getDatePickerCellValue, () => { + return ['YYYY']; + }), + renderItemContent: createFormItemRender(), + exportMethod: createExportMethod(getDatePickerCellValue, () => { + return ['YYYY']; + }), +}; diff --git a/src/components/VxeTable/src/components/common.tsx b/src/components/VxeTable/src/components/common.tsx new file mode 100644 index 0000000..f2ba1e3 --- /dev/null +++ b/src/components/VxeTable/src/components/common.tsx @@ -0,0 +1,427 @@ +import { ComponentOptions, h } from 'vue'; +import { + FormItemContentRenderParams, + FormItemRenderOptions, + VxeGlobalRendererHandles, +} from 'vxe-table'; +import XEUtils from 'xe-utils'; +import { componentMap } from '../componentMap'; +import { ComponentType } from '../componentType'; +import { createPlaceholderMessage } from '../helper'; + +/** + * @description: 获取组件 + */ +export function getComponent(componentName) { + const Component = componentMap.get(componentName as ComponentType); + if (!Component) throw `您还没注册此组件 ${componentName}`; + return Component as ComponentOptions; +} + +export function isEmptyValue(cellValue: any) { + return cellValue === null || cellValue === undefined || cellValue === ''; +} + +export function formatText(cellValue: any) { + return '' + (isEmptyValue(cellValue) ? '' : cellValue); +} + +export function cellText(cellValue: any): string[] { + return [formatText(cellValue)]; +} + +/** + * @description: 方法名转换 + */ +export function getOnName(type: string) { + return 'on' + type.substring(0, 1).toLocaleUpperCase() + type.substring(1); +} + +/** + * @description: 获取组件传值所接受的属性 + */ +function getModelKey(renderOpts: VxeGlobalRendererHandles.RenderOptions) { + let prop = 'value'; + switch (renderOpts.name) { + case 'ASwitch': + prop = 'checked'; + break; + } + return prop; +} + +/** + * @description: 回去双向更新的方法 + */ +function getModelEvent(renderOpts: VxeGlobalRendererHandles.RenderOptions) { + let type = 'update:value'; + switch (renderOpts.name) { + case 'ASwitch': + type = 'update:checked'; + break; + } + return type; +} + +/** + * @description: chang值改变方法 + * @param {} + * @return {*} + * @author: * + */ +function getChangeEvent() { + return 'change'; +} + +function getClickEvent() { + return 'click'; +} +/** + * @description: 获取方法 + * @param {} + * @return {*} + * @author: * + */ +export function createEvents( + renderOpts: VxeGlobalRendererHandles.RenderOptions, + params: VxeGlobalRendererHandles.RenderParams, + inputFunc?: Function, + changeFunc?: Function, + clickFunc?: Function, +) { + const { events } = renderOpts; + const modelEvent = getModelEvent(renderOpts); + const changeEvent = getChangeEvent(); + const clickEvent = getClickEvent(); + const isSameEvent = changeEvent === modelEvent; + const ons: { [type: string]: Function } = {}; + + XEUtils.objectEach(events, (func: Function, key: string) => { + ons[getOnName(key)] = function (...args: any[]) { + func(params, ...args); + }; + }); + if (inputFunc) { + ons[getOnName(modelEvent)] = function (targetEvnt: any) { + inputFunc(targetEvnt); + if (events && events[modelEvent]) { + events[modelEvent](params, targetEvnt); + } + if (isSameEvent && changeFunc) { + changeFunc(targetEvnt); + } + }; + } + if (!isSameEvent && changeFunc) { + ons[getOnName(changeEvent)] = function (...args: any[]) { + changeFunc(...args); + if (events && events[changeEvent]) { + events[changeEvent](params, ...args); + } + }; + } + if (clickFunc) { + ons[getOnName(clickEvent)] = function (...args: any[]) { + clickFunc(...args); + if (events && events[clickEvent]) { + events[clickEvent](params, ...args); + } + }; + } + return ons; +} + +/** + * @description: 获取属性 + */ +export function createProps( + renderOpts: VxeGlobalRendererHandles.RenderOptions, + value: any, + defaultProps?: { [prop: string]: any }, +) { + const name = renderOpts.name as ComponentType; + return XEUtils.assign( + { + placeholder: createPlaceholderMessage(name), + allowClear: true, + }, + defaultProps, + renderOpts.props, + { + [getModelKey(renderOpts)]: value, + }, + ); +} + +/** + * @description: 创建单元格默认显示内容 + */ +export function createDefaultRender( + defaultProps?: { [key: string]: any }, + callBack?: ( + renderOpts: VxeGlobalRendererHandles.RenderDefaultOptions, + params: VxeGlobalRendererHandles.RenderDefaultParams, + ) => Record, +) { + return function ( + renderOpts: VxeGlobalRendererHandles.RenderDefaultOptions, + params: VxeGlobalRendererHandles.RenderDefaultParams, + ) { + const { row, column, $table } = params; + const { name, attrs } = renderOpts; + const cellValue = XEUtils.get(row, column.field as string); + const args = (callBack && callBack(renderOpts, params)) ?? {}; + + const Component = getComponent(name); + return [ + h(Component, { + ...attrs, + ...createProps(renderOpts, cellValue, defaultProps), + ...args, + ...createEvents( + renderOpts, + params, + (value: any) => XEUtils.set(row, column.field as string, value), + () => $table.updateStatus(params), + ), + }), + ]; + }; +} + +/** + * @description: 创建编辑单元格 + */ +export function createEditRender( + defaultProps?: { [key: string]: any }, + callBack?: ( + renderOpts: VxeGlobalRendererHandles.RenderEditOptions, + params: VxeGlobalRendererHandles.RenderEditParams, + ) => Record, +) { + return function ( + renderOpts: VxeGlobalRendererHandles.RenderEditOptions, + params: VxeGlobalRendererHandles.RenderEditParams, + ) { + const { row, column, $table } = params; + const { name, attrs } = renderOpts; + const cellValue = XEUtils.get(row, column.field as string); + const args = (callBack && callBack(renderOpts, params)) ?? {}; + + const Component = getComponent(name); + return [ + h(Component, { + ...attrs, + ...createProps(renderOpts, cellValue, defaultProps), + ...args, + ...createEvents( + renderOpts, + params, + (value: any) => XEUtils.set(row, column.field as string, value), + () => $table.updateStatus(params), + ), + }), + ]; + }; +} + +/** + * @description: 创建筛选渲染内容 + */ +export function createFilterRender( + defaultProps?: { [key: string]: any }, + callBack?: ( + renderOpts: VxeGlobalRendererHandles.RenderFilterOptions, + params: VxeGlobalRendererHandles.RenderFilterParams, + ) => Record, +) { + return function ( + renderOpts: VxeGlobalRendererHandles.RenderFilterOptions, + params: VxeGlobalRendererHandles.RenderFilterParams, + ) { + const { column } = params; + const { name, attrs } = renderOpts; + const args = (callBack && callBack(renderOpts, params)) ?? {}; + + const Component = getComponent(name); + return [ + h( + 'div', + { + class: 'vxe-table--filter-antd-wrapper', + }, + column.filters.map((option, oIndex) => { + const optionValue = option.data; + const checked = !!option.data; + + return h(Component, { + key: oIndex, + ...attrs, + ...createProps(renderOpts, optionValue, defaultProps), + ...args, + ...createEvents( + renderOpts, + params, + (value: any) => { + // 处理 model 值双向绑定 + option.data = value; + }, + () => { + // 处理 change 事件相关逻辑 + const { $panel } = params; + $panel.changeOption(null, checked, option); + }, + ), + }); + }), + ), + ]; + }; +} + +/** + * @description: 默认过滤 + * @param {} + * @return {*} + * @author: * + */ + +export function createDefaultFilterRender() { + return function (params: VxeGlobalRendererHandles.FilterMethodParams) { + const { option, row, column } = params; + const { data } = option; + const cellValue = XEUtils.get(row, column.field as string); + return cellValue === data; + }; +} + +/** + * @description: 创建 form表单渲染 + */ +export function createFormItemRender( + defaultProps?: { [key: string]: any }, + callBack?: ( + renderOpts: FormItemRenderOptions, + params: FormItemContentRenderParams, + ) => Record, +) { + return function (renderOpts: FormItemRenderOptions, params: FormItemContentRenderParams) { + const args = (callBack && callBack(renderOpts, params)) ?? {}; + const { data, property, $form } = params; + const { name } = renderOpts; + const { attrs } = renderOpts; + const itemValue = XEUtils.get(data, property); + + const Component = getComponent(name); + return [ + h(Component, { + ...attrs, + ...createProps(renderOpts, itemValue, defaultProps), + ...args, + ...createEvents( + renderOpts, + params, + (value: any) => { + // 处理 model 值双向绑定 + XEUtils.set(data, property, value); + }, + () => { + // 处理 change 事件相关逻辑 + $form.updateStatus({ + ...params, + field: property, + }); + }, + ), + }), + ]; + }; +} + +/** + * @description: cell渲染 + */ +export function createCellRender( + getSelectCellValue: Function, + callBack?: ( + renderOpts: VxeGlobalRendererHandles.RenderCellOptions, + params: VxeGlobalRendererHandles.RenderCellParams, + ) => Array, +) { + return function ( + renderOpts: VxeGlobalRendererHandles.RenderCellOptions, + params: VxeGlobalRendererHandles.RenderCellParams, + ) { + const args = (callBack && callBack(renderOpts, params)) ?? []; + const cellLabel = getSelectCellValue && getSelectCellValue(renderOpts, params, ...args); + const { placeholder } = renderOpts; + + return [ + h( + 'span', + { + class: 'vxe-cell--label', + }, + placeholder && isEmptyValue(cellLabel) + ? [ + h( + 'span', + { + class: 'vxe-cell--placeholder', + }, + formatText(placeholder), + ), + ] + : formatText(cellLabel), + ), + ]; + }; +} + +/** + * @description: 创建 导出渲染 + * @param {} + * @return {*} + * @author: * + */ +export function createExportMethod( + getExportCellValue: Function, + callBack?: (params: VxeGlobalRendererHandles.ExportMethodParams) => Array, +) { + return function (params: VxeGlobalRendererHandles.ExportMethodParams) { + const { row, column, options } = params; + const args = (callBack && callBack(params)) ?? []; + return options && options.original + ? XEUtils.get(row, column.field as string) + : getExportCellValue(column.editRender || column.cellRender, params, ...args); + }; +} + +/** + * @description: 创建单元格默认显示内容 + */ +export function createToolbarToolRender( + defaultProps?: { [key: string]: any }, + callBack?: ( + renderOpts: VxeGlobalRendererHandles.RenderToolOptions, + params: VxeGlobalRendererHandles.RenderToolParams, + ) => Record, +) { + return function ( + renderOpts: VxeGlobalRendererHandles.RenderToolOptions, + params: VxeGlobalRendererHandles.RenderToolParams, + ) { + const { name, attrs } = renderOpts; + const args = (callBack && callBack(renderOpts, params)) ?? {}; + + const Component = getComponent(name); + return [ + h(Component, { + ...attrs, + ...createProps(renderOpts, null, defaultProps), + ...args, + ...createEvents(renderOpts, params), + }), + ]; + }; +} diff --git a/src/components/VxeTable/src/components/index.tsx b/src/components/VxeTable/src/components/index.tsx new file mode 100644 index 0000000..ba8c6d8 --- /dev/null +++ b/src/components/VxeTable/src/components/index.tsx @@ -0,0 +1,114 @@ +import { VXETableCore, VxeGlobalInterceptorHandles } from 'vxe-table'; +import AAutoComplete from './AAutoComplete'; +import AInput from './AInput'; +import AInputNumber from './AInputNumber'; +import ASelect from './ASelect'; +import ACascader from './ACascader'; +import ADatePicker from './ADatePicker'; +import AMonthPicker from './AMonthPicker'; +import ARangePicker from './ARangePicker'; +import AWeekPicker from './AWeekPicker'; +import ATreeSelect from './ATreeSelect'; +import ATimePicker from './ATimePicker'; +import ARate from './ARate'; +import ASwitch from './ASwitch'; +import ARadioGroup from './ARadioGroup'; +import ACheckboxGroup from './ACheckboxGroup'; +import AButton from './AButton'; +import AButtonGroup from './AButtonGroup'; +import AApiSelect from './AApiSelect'; +import AApiTreeSelect from './AApiTreeSelect'; +import AEmpty from './AEmpty'; +import AInputSearch from './AInputSearch'; +import AYearPicker from './AYearPicker'; + +/** + * 检查触发源是否属于目标节点 + */ +function getEventTargetNode(evnt: any, container: HTMLElement, className: string) { + let targetElem; + let target = evnt.target; + while (target && target.nodeType && target !== document) { + if ( + className && + target.className && + target.className.split && + target.className.split(' ').indexOf(className) > -1 + ) { + targetElem = target; + } else if (target === container) { + return { flag: className ? !!targetElem : true, container, targetElem: targetElem }; + } + target = target.parentNode; + } + return { flag: false }; +} + +/** + * 事件兼容性处理 + */ +function handleClearEvent( + params: + | VxeGlobalInterceptorHandles.InterceptorClearFilterParams + | VxeGlobalInterceptorHandles.InterceptorClearActivedParams + | VxeGlobalInterceptorHandles.InterceptorClearAreasParams, +) { + const { $event } = params; + const bodyElem = document.body; + if ( + // 下拉框 + getEventTargetNode($event, bodyElem, 'ant-select-dropdown').flag || + // 级联 + getEventTargetNode($event, bodyElem, 'ant-cascader-menus').flag || + // 日期 + getEventTargetNode($event, bodyElem, 'ant-calendar-picker-container').flag || + // 时间选择 + getEventTargetNode($event, bodyElem, 'ant-time-picker-panel').flag + ) { + return false; + } +} + +/** + * 基于 vxe-table 表格的适配插件,用于兼容 ant-design-vue 组件库 + */ +export const VXETablePluginAntd = { + install(vxetablecore: VXETableCore) { + const { interceptor, renderer } = vxetablecore; + + renderer.mixin({ + AAutoComplete, + AInput, + AInputNumber, + ASelect, + ACascader, + ADatePicker, + AMonthPicker, + ARangePicker, + AWeekPicker, + ATimePicker, + ATreeSelect, + ARate, + ASwitch, + ARadioGroup, + ACheckboxGroup, + AButton, + AButtonGroup, + AApiSelect, + AApiTreeSelect, + AEmpty, + AInputSearch, + AYearPicker, + }); + + interceptor.add('event.clearFilter', handleClearEvent); + interceptor.add('event.clearActived', handleClearEvent); + interceptor.add('event.clearAreas', handleClearEvent); + }, +}; + +if (typeof window !== 'undefined' && window.VXETable && window.VXETable.use) { + window.VXETable.use(VXETablePluginAntd); +} + +export default VXETablePluginAntd; diff --git a/src/components/VxeTable/src/const.ts b/src/components/VxeTable/src/const.ts new file mode 100644 index 0000000..6827bb4 --- /dev/null +++ b/src/components/VxeTable/src/const.ts @@ -0,0 +1,4 @@ +/** + * @description: 传给vxe-table 时需要忽略的prop + */ +export const ignorePropKeys = ['tableClass', 'tableStyle']; diff --git a/src/components/VxeTable/src/css/common.scss b/src/components/VxeTable/src/css/common.scss new file mode 100644 index 0000000..a8eb58e --- /dev/null +++ b/src/components/VxeTable/src/css/common.scss @@ -0,0 +1,8 @@ +*, +::before, +::after { + box-sizing: border-box; + border-width: 0; + border-style: solid; + border-color: initial; +} diff --git a/src/components/VxeTable/src/css/component.scss b/src/components/VxeTable/src/css/component.scss new file mode 100644 index 0000000..cbb3288 --- /dev/null +++ b/src/components/VxeTable/src/css/component.scss @@ -0,0 +1,123 @@ +/* stylelint-disable scss/percent-placeholder-pattern */ +%ResetBorder { + border: 0; + box-shadow: none; +} + +%CompWidth { + & > .ant-input, + & > .ant-input-number, + & > .ant-select, + & > .ant-cascader-picker, + & > .ant-calendar-picker, + & > .ant-time-picker { + width: 100%; + } +} + +.vxe-form { + .vxe-form--item-content { + @extend %CompWidth; + } +} + +.vxe-table--filter-antd-wrapper { + & > .ant-input, + & > .ant-input-number, + & > .ant-select, + & > .ant-rate { + width: 180px; + } +} + +.vxe-cell, +.vxe-tree-cell { + @extend %CompWidth; + + & > .ant-rate { + vertical-align: bottom; + + .anticon-star { + display: block; + } + } +} + +.col--valid-error { + & > .vxe-cell, + & > .vxe-tree-cell { + & > .ant-input, + & > .ant-select .ant-input, + & > .ant-select .ant-select-selection, + & > .ant-input-number, + & > .ant-cascader-picker .ant-cascader-input, + & > .ant-calendar-picker .ant-calendar-picker-input { + box-shadow: none; + } + } +} + +.vxe-table.cell--highlight { + .vxe-cell, + .vxe-tree-cell { + & > .ant-input, + & > .ant-input-number { + @extend %ResetBorder; + + padding: 0; + } + + & > .ant-select { + .ant-input { + @extend %ResetBorder; + + padding: 0; + } + + .ant-select-selection { + @extend %ResetBorder; + + .ant-select-selection__rendered { + margin: 0; + } + } + } + + & > .ant-input-number { + .ant-input-number-input { + padding: 0; + } + + .ant-input-number-handler-wrap, + .ant-input-number-handler-down { + @extend %ResetBorder; + } + } + + & > .ant-cascader-picker { + .ant-input { + @extend %ResetBorder; + } + + .ant-cascader-picker-label { + padding: 0; + } + } + + & > .ant-calendar-picker { + .ant-calendar-picker-input { + @extend %ResetBorder; + + padding: 0; + } + } + + & > .ant-time-picker { + .ant-time-picker-input { + @extend %ResetBorder; + + padding: 0; + } + } + } +} diff --git a/src/components/VxeTable/src/css/index.scss b/src/components/VxeTable/src/css/index.scss new file mode 100644 index 0000000..9dfc2a7 --- /dev/null +++ b/src/components/VxeTable/src/css/index.scss @@ -0,0 +1,5 @@ +@import './common'; +@import './variable'; +@import './toolbar'; +@import './component'; +// @import 'vxe-table/styles/index'; diff --git a/src/components/VxeTable/src/css/toolbar.scss b/src/components/VxeTable/src/css/toolbar.scss new file mode 100644 index 0000000..2b98e86 --- /dev/null +++ b/src/components/VxeTable/src/css/toolbar.scss @@ -0,0 +1,26 @@ +.vxe-toolbar .vxe-custom--option-wrapper .vxe-custom--footer { + display: flex; +} + +.vxe-toolbar .vxe-tools--wrapper, +.vxe-toolbar .vxe-tools--operate button:first-child { + margin: 0; + margin-left: 10px; +} + +.vxe-toolbar .vxe-tools--wrapper, +.vxe-toolbar .vxe-tools--operate .vxe-button { + margin-left: 1px; + border-radius: 0 !important; +} + +.vxe-toolbar .vxe-tools--wrapper, +.vxe-toolbar .vxe-tools--operate .vxe-custom--wrapper { + margin-left: 1px; + border-radius: 0 !important; +} + +.vxe-toolbar .vxe-tools--wrapper, +.vxe-toolbar .vxe-tools--operate .vxe-custom--wrapper .vxe-button { + margin-left: 10px; +} diff --git a/src/components/VxeTable/src/css/variable.scss b/src/components/VxeTable/src/css/variable.scss new file mode 100644 index 0000000..4f4e72e --- /dev/null +++ b/src/components/VxeTable/src/css/variable.scss @@ -0,0 +1,54 @@ +/* stylelint-disable scss/no-global-function-names */ +html[data-theme='dark'] { + // $bg-color: #151515; + // $tooltip-bg-color: #303133; + // $text-color: #c9d1d9; + // $border-color: #303030; + // $selected-bg-color: #1e1e1e; + // $striped-bg-color: #1e1e1e; + + --vxe-form-background-color: #151515; + --vxe-toolbar-background-color: #151515; + --vxe-pager-background-color: #151515; + --vxe-button-default-background-color: lighten(#151515, 15%); + --vxe-table-header-background-color: lighten(#151515, 5%); + --vxe-font-color: darken(#c9d1d9, 12%); + --vxe-table-header-font-color: #c9d1d9; + --vxe-table-footer-font-color: #c9d1d9; + --vxe-table-body-background-color: #151515; + --vxe-table-footer-background-color: #151515; + --vxe-table-row-striped-background-color: #1e1e1e; + --vxe-table-border-color: #303030; + --vxe-table-row-hover-background-color: #1e1e1e; + --vxe-table-row-hover-striped-background-color: darken(#1e1e1e, 10%); + --vxe-table-row-current-background-color: fade(#1e1e1e, 20%); + --vxe-table-row-hover-current-background-color: fade(#1e1e1e, 20%); + --vxe-table-column-hover-background-color: fade(#1e1e1e, 20%); + --vxe-table-column-current-background-color: fade(#1e1e1e, 20%); + --vxe-table-row-checkbox-checked-background-color: fade(#1e1e1e, 15%); + --vxe-table-row-hover-checkbox-checked-background-color: fade(#1e1e1e, 20%); + --vxe-table-menu-background-color: lighten(#303133, 10%); + --vxe-table-filter-panel-background-color: lighten(#151515, 5%); + --vxe-grid-maximize-background-color: #151515; + --vxe-pager-perfect-background-color: #151515; + --vxe-pager-perfect-button-background-color: lighten(#151515, 15%); + --vxe-input-background-color: #151515; + --vxe-input-border-color: #303030; + --vxe-select-panel-background-color: #151515; + --vxe-table-popup-border-color: #303030; + --vxe-select-option-hover-background-color: lighten(#1e1e1e, 15%); + --vxe-pulldown-panel-background-color: #151515; + --vxe-table-fixed-left-scrolling-box-shadow: 8px 0px 10px -5px rgb(255 255 255 / 12%); + --vxe-table-fixed-right-scrolling-box-shadow: -8px 0px 10px -5px rgb(255 255 255 / 12%); + --vxe-loading-background-color: rgb(0 0 0 / 50%); + --vxe-tooltip-dark-background-color: lighten(#303133, 25%); + --vxe-modal-header-background-color: #1e1e1e; + --vxe-modal-body-background-color: #303133; + --vxe-modal-border-color: #303030; + --vxe-toolbar-panel-background-color: #151515; + --vxe-input-disabled-color: lighten(#1e1e1e, 20%); + --vxe-input-disabled-background-color: lighten(#1e1e1e, 25%); + --vxe-checkbox-icon-background-color: lighten(#1e1e1e, 15%); + --vxe-checkbox-checked-icon-border-color: #303030; + --vxe-checkbox-indeterminate-icon-background-color: lighten(#1e1e1e, 15%); +} diff --git a/src/components/VxeTable/src/emits.ts b/src/components/VxeTable/src/emits.ts new file mode 100644 index 0000000..4920d73 --- /dev/null +++ b/src/components/VxeTable/src/emits.ts @@ -0,0 +1,17 @@ +import tableEmits from 'vxe-table/es/table/src/emits'; + +export const basicEmits = [ + ...tableEmits, + 'page-change', + 'form-submit', + 'form-submit-invalid', + 'form-reset', + 'form-collapse', + 'form-toggle-collapse', + 'toolbar-button-click', + 'toolbar-tool-click', + 'zoom', + + //... 如有缺少在此处追加 + // xxx +]; diff --git a/src/components/VxeTable/src/helper.ts b/src/components/VxeTable/src/helper.ts new file mode 100644 index 0000000..25e16b3 --- /dev/null +++ b/src/components/VxeTable/src/helper.ts @@ -0,0 +1,19 @@ +import { ComponentType } from './componentType'; +import { useI18n } from '@/hooks/web/useI18n'; + +const { t } = useI18n(); + +/** + * @description: 生成placeholder + */ +export function createPlaceholderMessage(component: ComponentType) { + if (!component) return; + if (component.includes('RangePicker')) { + return [t('common.chooseText'), t('common.chooseText')]; + } + if (component.includes('Input') || component.includes('Complete') || component.includes('Rate')) { + return t('common.inputText'); + } else { + return t('common.chooseText'); + } +} diff --git a/src/components/VxeTable/src/methods.ts b/src/components/VxeTable/src/methods.ts new file mode 100644 index 0000000..491ba9f --- /dev/null +++ b/src/components/VxeTable/src/methods.ts @@ -0,0 +1,170 @@ +import { + GridMethods, + TableMethods, + TableEditMethods, + TableValidatorMethods, + VxeGridConstructor, +} from 'vxe-table'; + +export const gridComponentMethodKeys: ( + | keyof GridMethods + | keyof TableMethods + | keyof TableEditMethods + | keyof TableValidatorMethods + | keyof VxeGridConstructor +)[] = [ + // vxe-grid 部分 + 'getRefMaps', + 'getComputeMaps', + 'dispatchEvent', + 'commitProxy', + 'getFormItems', + 'getPendingRecords', + 'zoom', + 'isMaximized', + 'maximize', + 'revert', + 'getProxyInfo', + + // vxe-table和vxe-grid公共部分 + 'clearAll', + 'syncData', + 'updateData', + 'loadData', + 'reloadData', + 'reloadRow', + 'loadColumn', + 'reloadColumn', + 'getRowNode', + 'getColumnNode', + 'getRowIndex', + 'getVTRowIndex', + 'getVMRowIndex', + 'getColumnIndex', + 'getVTColumnIndex', + 'getVMColumnIndex', + 'createData', + 'createRow', + 'revertData', + 'clearData', + 'isInsertByRow', + 'isUpdateByRow', + 'getColumns', + 'getColumnById', + 'getColumnByField', + 'getTableColumn', + 'getData', + 'getCheckboxRecords', + 'getParentRow', + 'getRowSeq', + 'getRowById', + 'getRowid', + 'getTableData', + 'hideColumn', + 'showColumn', + 'resetColumn', + 'refreshColumn', + 'refreshScroll', + 'recalculate', + 'closeTooltip', + 'isAllCheckboxChecked', + 'isAllCheckboxIndeterminate', + 'getCheckboxIndeterminateRecords', + 'setCheckboxRow', + 'isCheckedByCheckboxRow', + 'isIndeterminateByCheckboxRow', + 'toggleCheckboxRow', + 'setAllCheckboxRow', + 'getRadioReserveRecord', + 'clearRadioReserve', + 'getCheckboxReserveRecords', + 'clearCheckboxReserve', + 'toggleAllCheckboxRow', + 'clearCheckboxRow', + 'setCurrentRow', + 'isCheckedByRadioRow', + 'setRadioRow', + 'clearCurrentRow', + 'clearRadioRow', + 'getCurrentRecord', + 'getRadioRecord', + 'getCurrentColumn', + 'setCurrentColumn', + 'clearCurrentColumn', + 'sort', + 'clearSort', + 'isSort', + 'getSortColumns', + 'closeFilter', + 'isFilter', + 'isRowExpandLoaded', + 'clearRowExpandLoaded', + 'reloadRowExpand', + 'reloadRowExpand', + 'toggleRowExpand', + 'setAllRowExpand', + 'setRowExpand', + 'isExpandByRow', + 'clearRowExpand', + 'clearRowExpandReserve', + 'getRowExpandRecords', + 'getTreeExpandRecords', + 'isTreeExpandLoaded', + 'clearTreeExpandLoaded', + 'reloadTreeExpand', + 'reloadTreeChilds', + 'toggleTreeExpand', + 'setAllTreeExpand', + 'setTreeExpand', + 'isTreeExpandByRow', + 'clearTreeExpand', + 'clearTreeExpandReserve', + 'getScroll', + 'scrollTo', + 'scrollToRow', + 'scrollToColumn', + 'clearScroll', + 'updateFooter', + 'updateStatus', + 'setMergeCells', + 'removeInsertRow', + 'removeMergeCells', + 'getMergeCells', + 'clearMergeCells', + 'setMergeFooterItems', + 'removeMergeFooterItems', + 'getMergeFooterItems', + 'clearMergeFooterItems', + 'openTooltip', + 'focus', + 'blur', + 'connect', + + // vxe-table-edit部分 + 'insert', + 'insertAt', + 'remove', + 'removeCheckboxRow', + 'removeRadioRow', + 'removeCurrentRow', + 'getRecordset', + 'getInsertRecords', + 'getRemoveRecords', + 'getUpdateRecords', + 'getEditRecord', + 'getSelectedCell', + 'clearSelected', + 'isEditByRow', + 'setEditRow', + 'setEditCell', + 'setSelectCell', + 'clearEdit', + + // vxe-table-validator + 'clearValidate', + 'fullValidate', + 'validate', + + //... 如有缺少在此处追加 + // xxx +]; diff --git a/src/components/VxeTable/src/props.ts b/src/components/VxeTable/src/props.ts new file mode 100644 index 0000000..fff29de --- /dev/null +++ b/src/components/VxeTable/src/props.ts @@ -0,0 +1,52 @@ +import { VxeGridPropTypes, VxeTablePropTypes } from 'vxe-table'; +import tableProps from 'vxe-table/es/table/src/props'; +import { CSSProperties } from 'vue'; + +/** + * @description: table二次开发需要后,需要接受的所有prop属性 + */ +export const basicProps = { + ...tableProps, + columns: Array as PropType, + pagerConfig: { + type: Object as PropType, + default: () => ({}), + }, + proxyConfig: { + type: Object as PropType, + default: () => ({}), + }, + toolbarConfig: { + type: Object as PropType, + default: () => ({}), + }, + formConfig: { + type: Object as PropType, + default: () => ({}), + }, + zoomConfig: { + type: Object as PropType, + default: () => ({}), + }, + printConfig: { + type: Object as PropType, + default: () => ({}), + }, + exportConfig: { + type: Object as PropType, + default: () => ({}), + }, + importConfig: { + type: Object as PropType, + default: () => ({}), + }, + size: String as PropType, + tableClass: { + type: String, + default: '', + }, + tableStyle: { + type: Object as PropType, + default: () => ({}), + }, +}; diff --git a/src/components/VxeTable/src/setting.ts b/src/components/VxeTable/src/setting.ts new file mode 100644 index 0000000..ba3d061 --- /dev/null +++ b/src/components/VxeTable/src/setting.ts @@ -0,0 +1,4 @@ +import { VXETable } from '..'; +import componentSetting from '@/settings/componentSetting'; + +VXETable.setup(componentSetting.vxeTable); diff --git a/src/components/VxeTable/src/types.ts b/src/components/VxeTable/src/types.ts new file mode 100644 index 0000000..1319e69 --- /dev/null +++ b/src/components/VxeTable/src/types.ts @@ -0,0 +1,7 @@ +import { CSSProperties } from 'vue'; +import { VxeGridProps } from 'vxe-table'; + +export type BasicTableProps = VxeGridProps & { + tableClass?: string; + tableStyle?: CSSProperties; +}; diff --git a/src/components/illegalmining/PaginationComponent/index.vue b/src/components/illegalmining/PaginationComponent/index.vue new file mode 100644 index 0000000..f5eea08 --- /dev/null +++ b/src/components/illegalmining/PaginationComponent/index.vue @@ -0,0 +1,34 @@ + + + + + diff --git a/src/components/illegalmining/SearchComponent/index.vue b/src/components/illegalmining/SearchComponent/index.vue new file mode 100644 index 0000000..899c437 --- /dev/null +++ b/src/components/illegalmining/SearchComponent/index.vue @@ -0,0 +1,208 @@ + + + + + diff --git a/src/components/illegalmining/ShowListComponent/index.vue b/src/components/illegalmining/ShowListComponent/index.vue new file mode 100644 index 0000000..52aae74 --- /dev/null +++ b/src/components/illegalmining/ShowListComponent/index.vue @@ -0,0 +1,432 @@ + + + + + diff --git a/src/components/illegalmining/SortComponent/index.vue b/src/components/illegalmining/SortComponent/index.vue new file mode 100644 index 0000000..f10e489 --- /dev/null +++ b/src/components/illegalmining/SortComponent/index.vue @@ -0,0 +1,142 @@ + + + + + diff --git a/src/components/illegalmining/util.ts b/src/components/illegalmining/util.ts new file mode 100644 index 0000000..9312b4e --- /dev/null +++ b/src/components/illegalmining/util.ts @@ -0,0 +1,54 @@ +/** + * 年份 year + * 图斑来源 tubanlaiyuan + * 图斑类型 typename + * 县区 countyid + * 乡镇 streetid + * 处理状态 nowStatus + * 下发时间段 startTime-endTime + * 图斑号 caseNo + * 是否立案 register + */ +// 图斑来源 +import { getChildrenTree } from '@/api/demo/system'; +import { asyncGetOptions } from '@/utils/global'; + +const counties = await getChildrenTree({ parentId: 371300 }) + +export const polygonSourceOptions= await asyncGetOptions('tubanlaiyuan') +// 图斑类型 +export const polygonTypeOptions= await asyncGetOptions('kctubanleixing') +// 当前状态 +export const statusOptions = await asyncGetOptions('kcdangqianzhuangtai') +// 是否立案 +export const registerOptions =await asyncGetOptions('kcregister') +export const countiesOptions = counties.map(item => { + return { + label: item.name, + value: item.id + } +}) +export const orderUtils = { + 0: null, + 1: 'asc', + 2: 'desc', +} +export const usePageRequestUrl = { + 'patternfilling': '/api/DroneCaseInfoMinerals/LoadReportingTaskList', + 'fillingaudit': '/api/DroneCaseInfoMinerals/LoadReportingAuditTaskList', + 'patternexamining': '/api/DroneCaseInfoMinerals/LoadExaminingTaskList', + 'examiningaudit': '/api/DroneCaseInfoMinerals/LoadExaminingAuditTaskList', + 'patternrectification': '/api/DroneCaseInfoMinerals/LoadRectifyingTaskList', + 'rectificationaudit': '/api/DroneCaseInfoMinerals/LoadRectifyingAuditTaskList', + 'patternadjust': '/api/DroneCaseInfoMinerals/LoadModifyingTaskList', +} +export const usePageGetSearchItem = { + 'patternfilling': ["year", "tubanlaiyuan", "typename", "countyid", "streetid", "nowStatus", "time", "caseNo"], + 'fillingaudit': ["year", "tubanlaiyuan", "typename", "countyid", "caseNo"], + 'patternexamining': ["year", "tubanlaiyuan", "register", "countyid", "caseNo"], + 'examiningaudit': ["year", "tubanlaiyuan", "register", "countyid", "caseNo"], + 'patternrectification': ["year", "tubanlaiyuan", "countyid", "caseNo"], + 'rectificationaudit': ["year", "tubanlaiyuan", "countyid", "caseNo"], + 'patternadjust': ["year", "tubanlaiyuan", "countyid", "caseNo"], +} +export const smallInput:any = ['fillingaudit','patternexamining','examiningaudit'] \ No newline at end of file diff --git a/src/components/lrLayout/index.js b/src/components/lrLayout/index.js new file mode 100644 index 0000000..0d96de4 --- /dev/null +++ b/src/components/lrLayout/index.js @@ -0,0 +1,7 @@ +import lrLayout from './src/lrLayout.vue' + +lrLayout.install = function(Vue) { + Vue.component(lrLayout.name, lrLayout) +} + +export default lrLayout \ No newline at end of file diff --git a/src/components/lrLayout/src/lrLayout.vue b/src/components/lrLayout/src/lrLayout.vue new file mode 100644 index 0000000..c9afda4 --- /dev/null +++ b/src/components/lrLayout/src/lrLayout.vue @@ -0,0 +1,208 @@ + + + diff --git a/src/components/lrPanel/index.js b/src/components/lrPanel/index.js new file mode 100644 index 0000000..2db1350 --- /dev/null +++ b/src/components/lrPanel/index.js @@ -0,0 +1,7 @@ +import lrPanel from './src/lrPanel.vue' + +lrPanel.install = function(Vue) { + Vue.component(lrPanel.name, lrPanel) +} + +export default lrPanel \ No newline at end of file diff --git a/src/components/lrPanel/src/lrPanel.vue b/src/components/lrPanel/src/lrPanel.vue new file mode 100644 index 0000000..ee74446 --- /dev/null +++ b/src/components/lrPanel/src/lrPanel.vue @@ -0,0 +1,68 @@ + + + diff --git a/src/components/redlinesupervision/PaginationComponent/index.vue b/src/components/redlinesupervision/PaginationComponent/index.vue new file mode 100644 index 0000000..f5eea08 --- /dev/null +++ b/src/components/redlinesupervision/PaginationComponent/index.vue @@ -0,0 +1,34 @@ + + + + + diff --git a/src/components/redlinesupervision/SearchComponent/index.vue b/src/components/redlinesupervision/SearchComponent/index.vue new file mode 100644 index 0000000..899c437 --- /dev/null +++ b/src/components/redlinesupervision/SearchComponent/index.vue @@ -0,0 +1,208 @@ + + + + + diff --git a/src/components/redlinesupervision/ShowListComponent/index.vue b/src/components/redlinesupervision/ShowListComponent/index.vue new file mode 100644 index 0000000..f445b37 --- /dev/null +++ b/src/components/redlinesupervision/ShowListComponent/index.vue @@ -0,0 +1,429 @@ + + + + + diff --git a/src/components/redlinesupervision/SortComponent/index.vue b/src/components/redlinesupervision/SortComponent/index.vue new file mode 100644 index 0000000..f10e489 --- /dev/null +++ b/src/components/redlinesupervision/SortComponent/index.vue @@ -0,0 +1,142 @@ + + + + + diff --git a/src/components/redlinesupervision/util.ts b/src/components/redlinesupervision/util.ts new file mode 100644 index 0000000..9312b4e --- /dev/null +++ b/src/components/redlinesupervision/util.ts @@ -0,0 +1,54 @@ +/** + * 年份 year + * 图斑来源 tubanlaiyuan + * 图斑类型 typename + * 县区 countyid + * 乡镇 streetid + * 处理状态 nowStatus + * 下发时间段 startTime-endTime + * 图斑号 caseNo + * 是否立案 register + */ +// 图斑来源 +import { getChildrenTree } from '@/api/demo/system'; +import { asyncGetOptions } from '@/utils/global'; + +const counties = await getChildrenTree({ parentId: 371300 }) + +export const polygonSourceOptions= await asyncGetOptions('tubanlaiyuan') +// 图斑类型 +export const polygonTypeOptions= await asyncGetOptions('kctubanleixing') +// 当前状态 +export const statusOptions = await asyncGetOptions('kcdangqianzhuangtai') +// 是否立案 +export const registerOptions =await asyncGetOptions('kcregister') +export const countiesOptions = counties.map(item => { + return { + label: item.name, + value: item.id + } +}) +export const orderUtils = { + 0: null, + 1: 'asc', + 2: 'desc', +} +export const usePageRequestUrl = { + 'patternfilling': '/api/DroneCaseInfoMinerals/LoadReportingTaskList', + 'fillingaudit': '/api/DroneCaseInfoMinerals/LoadReportingAuditTaskList', + 'patternexamining': '/api/DroneCaseInfoMinerals/LoadExaminingTaskList', + 'examiningaudit': '/api/DroneCaseInfoMinerals/LoadExaminingAuditTaskList', + 'patternrectification': '/api/DroneCaseInfoMinerals/LoadRectifyingTaskList', + 'rectificationaudit': '/api/DroneCaseInfoMinerals/LoadRectifyingAuditTaskList', + 'patternadjust': '/api/DroneCaseInfoMinerals/LoadModifyingTaskList', +} +export const usePageGetSearchItem = { + 'patternfilling': ["year", "tubanlaiyuan", "typename", "countyid", "streetid", "nowStatus", "time", "caseNo"], + 'fillingaudit': ["year", "tubanlaiyuan", "typename", "countyid", "caseNo"], + 'patternexamining': ["year", "tubanlaiyuan", "register", "countyid", "caseNo"], + 'examiningaudit': ["year", "tubanlaiyuan", "register", "countyid", "caseNo"], + 'patternrectification': ["year", "tubanlaiyuan", "countyid", "caseNo"], + 'rectificationaudit': ["year", "tubanlaiyuan", "countyid", "caseNo"], + 'patternadjust': ["year", "tubanlaiyuan", "countyid", "caseNo"], +} +export const smallInput:any = ['fillingaudit','patternexamining','examiningaudit'] \ No newline at end of file diff --git a/src/components/registerGlobComp.ts b/src/components/registerGlobComp.ts new file mode 100644 index 0000000..a1b9dd8 --- /dev/null +++ b/src/components/registerGlobComp.ts @@ -0,0 +1,9 @@ +import type { App } from 'vue'; +// import { Button } from './Button'; +// import { Input, Layout } from 'ant-design-vue'; +import VXETable from 'vxe-table'; + +export function registerGlobComp(app: App) { + // app.use(Input).use(Button).use(Layout).use(VXETable); + app.use(VXETable); +} diff --git a/src/design/ant/btn.less b/src/design/ant/btn.less new file mode 100644 index 0000000..7741980 --- /dev/null +++ b/src/design/ant/btn.less @@ -0,0 +1,289 @@ +// button reset +.ant-btn { + &-link:hover, + &-link:focus, + &-link:active { + border-color: transparent !important; + } + + &-primary { + background-color: @button-primary-color; + color: @white; + + &:hover, + &:focus { + background-color: @button-primary-hover-color; + color: @white; + } + } + + &-primary:not(&-background-ghost):not([disabled]) { + color: @white; + } + + &-default { + border-color: @button-cancel-border-color; + background-color: @button-cancel-bg-color; + color: @button-cancel-color; + + &:hover, + &:focus { + border-color: @button-cancel-hover-border-color; + background-color: @button-cancel-hover-bg-color; + color: @button-cancel-hover-color; + } + } + + [data-theme='light'] &.ant-btn-link.is-disabled { + border-color: transparent !important; + background-color: transparent !important; + box-shadow: none; + color: rgb(0 0 0 / 25%); + text-shadow: none; + cursor: not-allowed !important; + } + + [data-theme='dark'] &.ant-btn-link.is-disabled { + border-color: transparent !important; + background-color: transparent !important; + box-shadow: none; + color: rgb(255 255 255 / 25%) !important; + text-shadow: none; + cursor: not-allowed !important; + } + + // color: @white; + + &-success.ant-btn-link:not([disabled='disabled']) { + color: @button-success-color; + + &:hover, + &:focus { + border-color: transparent; + color: @button-success-hover-color; + } + + &:active { + color: @button-success-active-color; + } + } + + &-success.ant-btn-link.ant-btn-loading, + &-warning.ant-btn-link.ant-btn-loading, + &-error.ant-btn-link.ant-btn-loading, + &-background-ghost.ant-btn-link.ant-btn-loading, + &.ant-btn-link.ant-btn-loading { + &::before { + background: transparent; + } + } + + &[disabled], + &[disabled]:hover { + // color: fade(@button-cancel-color, 40%) !important; + // background: fade(@button-cancel-bg-color, 40%) !important; + // border-color: fade(@button-cancel-border-color, 40%) !important; + border-color: #d9d9d9; + background: #f5f5f5; + color: rgb(0 0 0 / 25%); + text-shadow: none; + } + + &-success:not(.ant-btn-link, .is-disabled) { + border-color: @button-success-color; + background-color: @button-success-color; + color: @white; + //border-width: 0; + + &:hover, + &:focus { + border-color: @button-success-hover-color; + background-color: @button-success-hover-color; + color: @white; + } + + &:active { + border-color: @button-success-active-color; + background-color: @button-success-active-color; + } + } + + &-warning.ant-btn-link:not([disabled='disabled']) { + color: @button-warn-color; + + &:hover, + &:focus { + border-color: transparent; + color: @button-warn-hover-color; + } + + &:active { + color: @button-warn-active-color; + } + } + + &-warning:not(.ant-btn-link, .is-disabled) { + border-color: @button-warn-color; + background-color: @button-warn-color; + color: @white; + //border-width: 0; + + &:hover, + &:focus { + border-color: @button-warn-hover-color; + background-color: @button-warn-hover-color; + color: @white; + } + + &:active { + border-color: @button-warn-active-color; + background-color: @button-warn-active-color; + } + + //&[disabled], + //&[disabled]:hover { + // color: @white; + // background-color: fade(@button-warn-color, 40%); + // border-color: fade(@button-warn-color, 40%); + //} + } + + &-error.ant-btn-link:not([disabled='disabled']) { + color: @button-error-color; + + &:hover, + &:focus { + border-color: transparent; + color: @button-error-hover-color; + } + + &:active { + color: @button-error-active-color; + } + } + + &-error:not(.ant-btn-link, .is-disabled) { + border-color: @button-error-color; + background-color: @button-error-color; + color: @white; + //border-width: 0; + + &:hover, + &:focus { + border-color: @button-error-hover-color; + background-color: @button-error-hover-color; + color: @white; + } + + &:active { + border-color: @button-error-active-color; + background-color: @button-error-active-color; + } + + //&[disabled], + //&[disabled]:hover { + // color: @white; + // background-color: fade(@button-error-color, 40%); + // border-color: fade(@button-error-color, 40%); + //} + } + + &-background-ghost { + border-width: 1px; + background-color: transparent !important; + + &[disabled], + &[disabled]:hover { + border-color: fade(@white, 40%) !important; + background-color: transparent !important; + color: fade(@white, 40%) !important; + } + } + + &-dashed&-background-ghost, + &-default&-background-ghost { + border-color: @button-ghost-color; + color: @button-ghost-color; + + &:hover, + &:focus { + border-color: @button-ghost-hover-color; + color: @button-ghost-hover-color; + } + + &:active { + border-color: @button-ghost-active-color; + color: @button-ghost-active-color; + } + + &[disabled], + &[disabled]:hover { + border-color: fade(@white, 40%) !important; + color: fade(@white, 40%) !important; + } + } + + &-background-ghost&-success:not(.ant-btn-link) { + border-width: 1px; + border-color: @button-success-color; + background-color: transparent; + color: @button-success-color; + + &:hover, + &:focus { + border-color: @button-success-hover-color; + color: @button-success-hover-color !important; + } + + &:active { + border-color: @button-success-active-color; + color: @button-success-active-color; + } + } + + &-background-ghost&-warning:not(.ant-btn-link) { + border-width: 1px; + border-color: @button-warn-color; + background-color: transparent; + color: @button-warn-color; + + &:hover, + &:focus { + border-color: @button-warn-hover-color; + color: @button-warn-hover-color !important; + } + + &:active { + border-color: @button-warn-active-color; + color: @button-warn-active-color; + } + } + + &-background-ghost&-error:not(.ant-btn-link) { + border-width: 1px; + border-color: @button-error-color; + background-color: transparent; + color: @button-error-color; + + &:hover, + &:focus { + border-color: @button-error-hover-color; + color: @button-error-hover-color !important; + } + + &:active { + border-color: @button-error-active-color; + color: @button-error-active-color; + } + } + + &-ghost.ant-btn-link:not([disabled='disabled']) { + color: @button-ghost-color; + + &:hover, + &:focus { + border-color: transparent; + color: @button-ghost-hover-color; + } + } +} diff --git a/src/design/ant/index.less b/src/design/ant/index.less new file mode 100644 index 0000000..2807f83 --- /dev/null +++ b/src/design/ant/index.less @@ -0,0 +1,64 @@ +@import './pagination.less'; +@import './input.less'; +@import './btn.less'; +@import './popconfirm.less'; + +.ant-image-preview-root { + img { + display: unset; + } +} + +.ant-back-top { + right: 20px; + bottom: 20px; +} + +.collapse-container__body { + > .ant-descriptions { + margin-left: 6px; + } +} + +.ant-image-preview-operations { + background-color: rgb(0 0 0 / 30%); +} + +.ant-popover { + &-content { + box-shadow: 0 2px 12px 0 rgb(0 0 0 / 10%); + } +} + +// ================================= +// ==============modal message====== +// ================================= +.modal-icon-warning { + color: @warning-color !important; +} + +.modal-icon-success { + color: @success-color !important; +} + +.modal-icon-error { + color: @error-color !important; +} + +.modal-icon-info { + color: @primary-color !important; +} + +.ant-checkbox-checked .ant-checkbox-inner::after, +.ant-tree-checkbox-checked .ant-tree-checkbox-inner::after { + border-top: 0 !important; + border-left: 0 !important; +} + +.ant-form-item-control-input-content { + > div { + > div { + max-width: 100%; + } + } +} diff --git a/src/design/ant/input.less b/src/design/ant/input.less new file mode 100644 index 0000000..8245fb7 --- /dev/null +++ b/src/design/ant/input.less @@ -0,0 +1,27 @@ +@import (reference) '../color.less'; + +// input +.ant-input { + &-number, + &-number-group-wrapper { + width: 100% !important; + min-width: 110px; + max-width: 100%; + } +} + +.ant-input-affix-wrapper .ant-input-suffix { + right: 9px; +} + +.ant-input-clear-icon { + margin-right: 5px; +} + +.ant-input-affix-wrapper-textarea-with-clear-btn { + padding: 0 !important; + + textarea.ant-input { + padding: 4px; + } +} diff --git a/src/design/ant/pagination.less b/src/design/ant/pagination.less new file mode 100644 index 0000000..0fb6711 --- /dev/null +++ b/src/design/ant/pagination.less @@ -0,0 +1,96 @@ +html[data-theme='dark'] { + .ant-pagination { + &.mini { + .ant-pagination-prev, + .ant-pagination-next, + .ant-pagination-item { + background-color: rgb(255 255 255 / 4%) !important; + + a { + color: #8b949e !important; + } + } + + .ant-select-arrow { + color: @text-color-secondary !important; + } + + .ant-pagination-item-active { + border: none; + border-radius: none !important; + background-color: @primary-color !important; + + a { + color: @white !important; + } + } + } + } +} + +.ant-pagination { + &.mini { + .ant-pagination-prev, + .ant-pagination-next { + border: 1px solid; + color: @text-color-base; + font-size: 12px; + } + + .ant-pagination-prev:hover, + .ant-pagination-next:hover, + .ant-pagination-item:focus, + .ant-pagination-item:hover { + a { + color: @primary-color; + } + } + + .ant-pagination-prev, + .ant-pagination-next, + .ant-pagination-item { + margin: 0 4px !important; + border: none; + border-radius: none !important; + background-color: #f4f4f5 !important; + + a { + margin-top: 1px; + color: #606266; + } + + &:last-child { + margin-right: 0 !important; + } + } + + .ant-pagination-item-active { + border: none; + border-radius: none !important; + background-color: @primary-color !important; + + a { + color: @white !important; + } + } + + .ant-pagination-options { + margin-left: 12px; + } + + .ant-pagination-options-quick-jumper input { + height: 22px; + margin: 0 6px; + line-height: 22px; + text-align: center; + } + + .ant-select-arrow { + color: @border-color-shallow-dark; + } + } + + &-disabled { + display: none !important; + } +} diff --git a/src/design/ant/popconfirm.less b/src/design/ant/popconfirm.less new file mode 100644 index 0000000..56bb18a --- /dev/null +++ b/src/design/ant/popconfirm.less @@ -0,0 +1,7 @@ +// 修复气泡确认框内的按钮在内容宽度不够换行的情况 +// 初始问题发现在 2.10.1 版本 固定列页面 http://ip:port/#/comp/table/fixedColumn +.ant-popconfirm { + &-buttons { + white-space: nowrap; + } +} diff --git a/src/design/ant/table.less b/src/design/ant/table.less new file mode 100644 index 0000000..fd50da7 --- /dev/null +++ b/src/design/ant/table.less @@ -0,0 +1,72 @@ +@prefix-cls: ~'@{namespace}-basic-table'; + +// fix table unnecessary scrollbar +.@{prefix-cls} { + .hide-scrollbar-y { + .ant-spin-nested-loading { + .ant-spin-container { + .ant-table { + .ant-table-content { + .ant-table-scroll { + .ant-table-hide-scrollbar { + overflow-y: auto !important; + } + + .ant-table-body { + overflow-y: auto !important; + } + } + + .ant-table-fixed-right { + .ant-table-body-outer { + .ant-table-body-inner { + overflow-y: auto !important; + } + } + } + + .ant-table-fixed-left { + .ant-table-body-outer { + .ant-table-body-inner { + overflow-y: auto !important; + } + } + } + } + } + } + } + } + + .hide-scrollbar-x { + .ant-spin-nested-loading { + .ant-spin-container { + .ant-table { + .ant-table-content { + .ant-table-scroll { + .ant-table-body { + overflow: auto !important; + } + } + + .ant-table-fixed-right { + .ant-table-body-outer { + .ant-table-body-inner { + overflow-x: auto !important; + } + } + } + + .ant-table-fixed-left { + .ant-table-body-outer { + .ant-table-body-inner { + overflow-x: auto !important; + } + } + } + } + } + } + } + } +} diff --git a/src/design/color.less b/src/design/color.less new file mode 100644 index 0000000..ea2251f --- /dev/null +++ b/src/design/color.less @@ -0,0 +1,197 @@ +html { + // text + --text-color: rgba(0 0 0 / 85%); + + // border + --border-color: #eee; + + // header + --header-bg-color: #394664; + --header-bg-hover-color: #273352; + --header-active-menu-bg-color: #273352; + + // sider + --sider-dark-bg-color: #273352; + --sider-dark-darken-bg-color: #273352; + --sider-dark-lighten-bg-color: #273352; + + // component + --component-background-color: #fff; + + // component-onlineform-formdesign + --component-onlineform-formdesign-background-color: #EBEDF1; + --component-onlineform-formdesign-alert-background-color: #FFFBE6; + + // app + --app-content-background-color: #fafafa; + + // custom color example + --custom-example-color: #ff4d4f; + + // dark theme + &[data-theme='dark'] { + // text + --text-color: #c9d1d9; + + // border + --border-color: #303030; + + // component + --component-background-color: #151515; + + // component-onlineform-formdesign + --component-onlineform-formdesign-background-color: #303030; + --component-onlineform-formdesign-alert-background-color: #303030; + + // app + --app-content-background-color: #1e1e1e; + + // custom color example + --custom-example-color: #55d187; + } +} + +@white: #fff; + +@content-bg: #f4f7f9; + +@border-color-base: var(--border-color); + +@text-color-secondary: #8b949e; + +@component-background: var(--component-background-color); + +@component-onlineform-formdesign-background-color: var(--component-onlineform-formdesign-background-color); +@component-onlineform-formdesign-alert-background-color: var(--component-onlineform-formdesign-alert-background-color); + +// :export { +// name: "less"; +// mainColor: @mainColor; +// fontSize: @fontSize; +// } +@iconify-bg-color: #5551; + +// ================================= +// =========border-color============ +// ================================= + +// Dark-dark +@border-color-dark: #b6b7b9; + +// Dark-light +@border-color-shallow-dark: #cececd; + +// Light-dark +@border-color-light: @border-color-base; + +// ================================= +// ============message============== +// ================================= + +// success-bg-color +@success-background-color: #f1f9ec; +// info-bg-color +@info-background-color: #e8eff8; +// warn-bg-color +@warning-background-color: #fdf6ed; +// danger-bg-color +@danger-background-color: #fef0f0; + +// ================================= +// ==============Header============= +// ================================= +@header-dark-bg-color: var(--header-bg-color); +@header-dark-bg-hover-color: var(--header-bg-hover-color); +@header-light-bg-hover-color: #f6f6f6; +@header-light-desc-color: #7c8087; +@header-light-bottom-border-color: #eee; +// top-menu +@top-menu-active-bg-color: var(--header-active-menu-bg-color); + +// ================================= +// ==============Menu=============== +// ================================= + +// let -menu +@sider-dark-bg-color: var(--sider-dark-bg-color); +@sider-dark-darken-bg-color: var(--sider-dark-darken-bg-color); +@sider-dark-lighten-bg-color: var(--sider-dark-lighten-bg-color); + +// trigger +@trigger-dark-hover-bg-color: rgba(255, 255, 255, 0.2); +@trigger-dark-bg-color: rgba(255, 255, 255, 0.1); + +// ================================= +// ==============tree=============== +// ================================= +// tree item hover background +@tree-hover-background-color: #f5f7fa; +// tree item hover font color +@tree-hover-font-color: #f5f7fa; + +// ================================= +// ==============link=============== +// ================================= +@link-hover-color: @primary-color; +@link-active-color: darken(@primary-color, 10%); + +// ================================= +// ===========Text color============ +// ================================= + +// Main text color +@text-color-base: var(--text-color); + +// ================================= +// =======app content color========= +// ================================= +@app-content-background: var(--app-content-background-color); + +// Label color +@text-color-call-out: #606266; + +// Auxiliary information color-dark +@text-color-help-dark: #909399; + +// ================================= +// ============breadcrumb=========== +// ================================= +@breadcrumb-item-normal-color: #999; +// ================================= +// ==============button============= +// ================================= + +@button-primary-color: @primary-color; +@button-primary-hover-color: lighten(@primary-color, 5%); +@button-primary-active-color: darken(@primary-color, 5%); + +@button-ghost-color: @white; +@button-ghost-hover-color: lighten(@white, 10%); +@button-ghost-hover-bg-color: #e1ebf6; +@button-ghost-active-color: darken(@white, 10%); + +@button-success-color: @success-color; +@button-success-hover-color: lighten(@success-color, 10%); +@button-success-active-color: darken(@success-color, 10%); + +@button-warn-color: @warning-color; +@button-warn-hover-color: lighten(@warning-color, 10%); +@button-warn-active-color: darken(@warning-color, 10%); + +@button-error-color: @error-color; +@button-error-hover-color: lighten(@error-color, 10%); +@button-error-active-color: darken(@error-color, 10%); + +@button-cancel-color: @text-color-call-out; +@button-cancel-bg-color: @white; +@button-cancel-border-color: @border-color-shallow-dark; + +// Mouse over +@button-cancel-hover-color: @primary-color; +@button-cancel-hover-bg-color: @white; +@button-cancel-hover-border-color: @primary-color; + +// ================================= +// =====custom color example======== +// ================================= +@custom-example-color: var(--custom-example-color); diff --git a/src/design/config.less b/src/design/config.less new file mode 100644 index 0000000..64c33f6 --- /dev/null +++ b/src/design/config.less @@ -0,0 +1,2 @@ +@import (reference) 'color.less'; +@import (reference) 'var/index.less'; diff --git a/src/design/entry.css b/src/design/entry.css new file mode 100644 index 0000000..1d40f5d --- /dev/null +++ b/src/design/entry.css @@ -0,0 +1,168 @@ +* > .enter-x:nth-child(1) { + transform: translateX(50px); +} +* > .-enter-x:nth-child(1) { + transform: translateX(-50px); +} + +* > .enter-x:nth-child(1), +* > .-enter-x:nth-child(1) { + z-index: 9; + opacity: 0; + animation: enter-x-animation 0.4s ease-in-out 0.3s; + animation-fill-mode: forwards; + animation-delay: 0.1s; +} +* > .enter-x:nth-child(2) { + transform: translateX(50px); +} +* > .-enter-x:nth-child(2) { + transform: translateX(-50px); +} + +* > .enter-x:nth-child(2), +* > .-enter-x:nth-child(2) { + z-index: 8; + opacity: 0; + animation: enter-x-animation 0.4s ease-in-out 0.3s; + animation-fill-mode: forwards; + animation-delay: 0.2s; +} +* > .enter-x:nth-child(3) { + transform: translateX(50px); +} +* > .-enter-x:nth-child(3) { + transform: translateX(-50px); +} + +* > .enter-x:nth-child(3), +* > .-enter-x:nth-child(3) { + z-index: 7; + opacity: 0; + animation: enter-x-animation 0.4s ease-in-out 0.3s; + animation-fill-mode: forwards; + animation-delay: 0.3s; +} + +* > .enter-x:nth-child(4) { + transform: translateX(50px); +} +* > .-enter-x:nth-child(4) { + transform: translateX(-50px); +} + +* > .enter-x:nth-child(4), +* > .-enter-x:nth-child(4) { + z-index: 6; + opacity: 0; + animation: enter-x-animation 0.4s ease-in-out 0.3s; + animation-fill-mode: forwards; + animation-delay: 0.4s; +} + +* > .enter-x:nth-child(5) { + transform: translateX(50px); +} +* > .-enter-x:nth-child(5) { + transform: translateX(-50px); +} + +* > .enter-x:nth-child(5), +* > .-enter-x:nth-child(5) { + z-index: 5; + opacity: 0; + animation: enter-x-animation 0.4s ease-in-out 0.3s; + animation-fill-mode: forwards; + animation-delay: 0.5s; +} + +* > .enter-y:nth-child(1) { + transform: translateX(50px); +} +* > .-enter-y:nth-child(1) { + transform: translateX(-50px); +} + +* > .enter-y:nth-child(1), +* > .-enter-y:nth-child(1) { + z-index: 9; + opacity: 0; + animation: enter-y-animation 0.4s ease-in-out 0.3s; + animation-fill-mode: forwards; + animation-delay: 0.1s; +} +* > .enter-y:nth-child(2) { + transform: translateX(50px); +} +* > .-enter-y:nth-child(2) { + transform: translateX(-50px); +} + +* > .enter-y:nth-child(2), +* > .-enter-y:nth-child(2) { + z-index: 8; + opacity: 0; + animation: enter-y-animation 0.4s ease-in-out 0.3s; + animation-fill-mode: forwards; + animation-delay: 0.2s; +} +* > .enter-y:nth-child(3) { + transform: translateX(50px); +} +* > .-enter-y:nth-child(3) { + transform: translateX(-50px); +} + +* > .enter-y:nth-child(3), +* > .-enter-y:nth-child(3) { + z-index: 7; + opacity: 0; + animation: enter-y-animation 0.4s ease-in-out 0.3s; + animation-fill-mode: forwards; + animation-delay: 0.3s; +} + +* > .enter-y:nth-child(4) { + transform: translateX(50px); +} +* > .-enter-y:nth-child(4) { + transform: translateX(-50px); +} + +* > .enter-y:nth-child(4), +* > .-enter-y:nth-child(4) { + z-index: 6; + opacity: 0; + animation: enter-y-animation 0.4s ease-in-out 0.3s; + animation-fill-mode: forwards; + animation-delay: 0.4s; +} + +* > .enter-y:nth-child(5) { + transform: translateX(50px); +} +* > .-enter-y:nth-child(5) { + transform: translateX(-50px); +} + +* > .enter-y:nth-child(5), +* > .-enter-y:nth-child(5) { + z-index: 5; + opacity: 0; + animation: enter-y-animation 0.4s ease-in-out 0.3s; + animation-fill-mode: forwards; + animation-delay: 0.5s; +} + +@keyframes enter-x-animation { + to { + opacity: 1; + transform: translateX(0); + } +} +@keyframes enter-y-animation { + to { + opacity: 1; + transform: translateY(0); + } +} diff --git a/src/design/index.less b/src/design/index.less new file mode 100644 index 0000000..e8ad79f --- /dev/null +++ b/src/design/index.less @@ -0,0 +1,93 @@ +@import 'color.less'; +@import 'transition/index.less'; +@import 'var/index.less'; +@import 'public.less'; +@import 'ant/index.less'; +@import 'theme.less'; +@import 'entry.css'; + +input:-webkit-autofill { + box-shadow: 0 0 0 1000px transparent inset; + -webkit-text-fill-color: @text-color-base; +} + +:-webkit-autofill { + transition: background-color 5000s ease-in-out 0s !important; +} + +html { + overflow: hidden; + text-size-adjust: 100%; +} + +html, +body { + position: relative; + width: 100%; + height: 100%; + overflow: hidden; + + &.color-weak { + filter: invert(80%); + } + + &.gray-mode { + filter: grayscale(100%); + filter: progid:dximagetransform.microsoft.basicimage(grayscale=1); + } +} + +a:focus, +a:active, +button, +div, +svg, +span { + outline: none; +} + +// 保持 和 windi 一样的全局样式,减少升级带来的影响 +ul { + margin: 0; + padding: 0; + list-style: none; +} +.card-always{ + border-color: transparent; + box-shadow: 0 1px 2px -2px rgba(0, 0, 0, 0.16), 0 3px 6px 0 rgba(0, 0, 0, 0.12), 0 5px 12px 4px rgba(0, 0, 0, 0.09); +} +.card-hover{ + transition: box-shadow 0.2s, border-color 0.2s; +} +.card-hover:hover{ + border-color: transparent; + box-shadow: 0 1px 2px -2px rgba(0, 0, 0, 0.16), 0 3px 6px 0 rgba(0, 0, 0, 0.12), 0 5px 12px 4px rgba(0, 0, 0, 0.09); +} +// 修改全局输入框 disable时背景颜色改浅,字体加深 +.ant-input-affix-wrapper-disabled, .ant-input-number-disabled{ + background-color: rgba(0, 0, 0, 0.01); +} +.ant-input[disabled]{ + color: rgba(0, 0, 0, 0.8); + background-color: rgba(0, 0, 0, 0.01); +} +.ant-radio-wrapper-disabled{ + color: rgba(0, 0, 0, 0.8); +} +.ant-image-preview-operations{ + background-color: rgba(0, 0, 0, 0); + span{ + font-size: 25px; + } +} +.ant-radio-disabled .ant-radio-inner::after { + background-color: rgba(0, 0, 0, 0.7); +} +.ant-radio-disabled .ant-radio-inner { + border-color: rgba(0, 0, 0, 0.2); +} +.ant-select-disabled .ant-select-selector{ + color: rgba(0, 0, 0, 0.8) !important; + background: rgba(0, 0, 0, 0.01) !important; +} + diff --git a/src/design/public.less b/src/design/public.less new file mode 100644 index 0000000..0323b84 --- /dev/null +++ b/src/design/public.less @@ -0,0 +1,55 @@ +#app { + width: 100%; + height: 100%; +} + +// ================================= +// ==============scrollbar========== +// ================================= + +::-webkit-scrollbar { + width: 7px; + height: 8px; +} + +// ::-webkit-scrollbar-track { +// background: transparent; +// } + +::-webkit-scrollbar-track { + background-color: rgb(0 0 0 / 5%); +} + +::-webkit-scrollbar-thumb { + // background-color: rgba(144, 147, 153, 0.3); + border-radius: 2px; + // background: rgba(0, 0, 0, 0.6); + background-color: rgb(144 147 153 / 30%); + box-shadow: inset 0 0 6px rgb(0 0 0 / 20%); +} + +::-webkit-scrollbar-thumb:hover { + background-color: @border-color-dark; +} + +::-webkit-scrollbar-corner { + background-color: transparent; +} + +// ================================= +// ==============nprogress========== +// ================================= +#nprogress { + pointer-events: none; + + .bar { + position: fixed; + z-index: 99999; + top: 0; + left: 0; + width: 100%; + height: 2px; + opacity: 0.75; + background-color: @primary-color; + } +} diff --git a/src/design/theme.less b/src/design/theme.less new file mode 100644 index 0000000..d17d868 --- /dev/null +++ b/src/design/theme.less @@ -0,0 +1,139 @@ +.bg-white { + background-color: var(--component-background-color) !important; +} + +html[data-theme='light'] { + .text-secondary { + color: rgb(0 0 0 / 45%); + } + + .ant-alert-success { + border: 1px solid #b7eb8f; + background-color: #f6ffed; + } + + .ant-alert-error { + border: 1px solid #ffccc7; + background-color: #fff2f0; + } + + .ant-alert-warning { + border: 1px solid #ffe58f; + background-color: #fffbe6; + } + + :not(:root):fullscreen::backdrop { + background-color: @layout-body-background !important; + } +} + +[data-theme='dark'] { + body { + background-color: #000; + color: @text-color-base; + } + + .ant-btn { + &[disabled], + &[disabled]:hover, + &[disabled]:focus, + &[disabled]:active { + border-color: #303030; + background: rgb(255 255 255 / 8%); + color: rgb(255 255 255 / 30%); + } + + &-success.ant-btn-link.ant-btn-loading, + &-warning.ant-btn-link.ant-btn-loading, + &-error.ant-btn-link.ant-btn-loading, + &-background-ghost.ant-btn-link.ant-btn-loading, + &.ant-btn-link.ant-btn-loading { + &::before { + background: transparent; + } + } + + &:not( + .ant-btn-link, + .is-disabled, + .ant-btn-primary, + .ant-btn-success, + .ant-btn-warning, + .ant-btn-error, + .ant-btn-dangerous + ) { + background: transparent; + color: @text-color-base; + + &:hover { + color: @button-primary-hover-color; + } + } + + &-dangerous.ant-btn-primary { + &:focus { + background: @error-color !important; + } + } + + &-default.ant-btn-dangerous { + border-color: @error-color; + background: transparent !important; + color: @error-color; + + &:hover, + &:focus { + border-color: @button-error-hover-color !important; + color: @button-error-hover-color !important; + } + } + + &-default:not(.ant-btn-background-ghost) { + border-color: #303030; + + &:hover, + &:focus { + border-color: @button-cancel-hover-color; + color: @button-cancel-hover-color; + } + } + + &-default.is-disabled { + &:hover, + &:focus { + border-color: #303030; + color: rgb(255 255 255 / 30%); + } + } + + &-success:not(.is-disabled, .ant-btn-link, .ant-btn-background-ghost) { + &:hover, + &:focus, + &:active { + border-color: @button-success-active-color !important; + background-color: @button-success-active-color !important; + color: @white !important; + } + } + + &-warning:not(.is-disabled, .ant-btn-link, .ant-btn-background-ghost) { + &:hover, + &:focus, + &:active { + border-color: @button-warn-active-color !important; + background-color: @button-warn-active-color !important; + color: @white !important; + } + } + + &-error:not(.is-disabled, .ant-btn-link, .ant-btn-background-ghost) { + &:hover, + &:focus, + &:active { + border-color: @button-error-active-color !important; + background-color: @button-error-active-color !important; + color: @white !important; + } + } + } +} diff --git a/src/design/transition/base.less b/src/design/transition/base.less new file mode 100644 index 0000000..7944c8b --- /dev/null +++ b/src/design/transition/base.less @@ -0,0 +1,18 @@ +.transition-default() { + &-enter-active, + &-leave-active { + transition: 0.3s cubic-bezier(0.25, 0.8, 0.5, 1) !important; + } + + &-move { + transition: transform 0.4s; + } +} + +.expand-transition { + .transition-default(); +} + +.expand-x-transition { + .transition-default(); +} diff --git a/src/design/transition/fade.less b/src/design/transition/fade.less new file mode 100644 index 0000000..70c79c5 --- /dev/null +++ b/src/design/transition/fade.less @@ -0,0 +1,97 @@ +.fade-transition { + &-enter-active, + &-leave-active { + transition: opacity 0.2s ease-in-out; + } + + &-enter-from, + &-leave-to { + opacity: 0; + } +} + +.fade-enter-active, +.fade-leave-active { + transition: opacity 0.2s ease-in-out; +} + +.fade-enter-from, +.fade-leave-to { + opacity: 0; +} + +/* fade-slide */ +.fade-slide-leave-active, +.fade-slide-enter-active { + transition: all 0.3s; +} + +.fade-slide-enter-from { + transform: translateX(-30px); + opacity: 0; +} + +.fade-slide-leave-to { + transform: translateX(30px); + opacity: 0; +} + +// /////////////////////////////////////////////// +// Fade Bottom +// /////////////////////////////////////////////// + +// Speed: 1x +.fade-bottom-enter-active, +.fade-bottom-leave-active { + transition: + opacity 0.25s, + transform 0.3s; +} + +.fade-bottom-enter-from { + transform: translateY(-10%); + opacity: 0; +} + +.fade-bottom-leave-to { + transform: translateY(10%); + opacity: 0; +} + +// fade-scale +.fade-scale-leave-active, +.fade-scale-enter-active { + transition: all 0.28s; +} + +.fade-scale-enter-from { + transform: scale(1.2); + opacity: 0; +} + +.fade-scale-leave-to { + transform: scale(0.8); + opacity: 0; +} + +// /////////////////////////////////////////////// +// Fade Top +// /////////////////////////////////////////////// + +// Speed: 1x +.fade-top-enter-active, +.fade-top-leave-active { + transition: + opacity 0.2s, + transform 0.25s; +} + +.fade-top-enter-from { + transform: translateY(8%); + opacity: 0; +} + +.fade-top-leave-to { + transform: translateY(-8%); + opacity: 0; +} diff --git a/src/design/transition/index.less b/src/design/transition/index.less new file mode 100644 index 0000000..8105d90 --- /dev/null +++ b/src/design/transition/index.less @@ -0,0 +1,13 @@ +@import './base.less'; +@import './fade.less'; +@import './scale.less'; +@import './slide.less'; +@import './scroll.less'; +@import './zoom.less'; + +.collapse-transition { + transition: + 0.2s height ease-in-out, + 0.2s padding-top ease-in-out, + 0.2s padding-bottom ease-in-out; +} diff --git a/src/design/transition/scale.less b/src/design/transition/scale.less new file mode 100644 index 0000000..521fce3 --- /dev/null +++ b/src/design/transition/scale.less @@ -0,0 +1,21 @@ +.scale-transition { + .transition-default(); + + &-enter-from, + &-leave, + &-leave-to { + transform: scale(0); + opacity: 0; + } +} + +.scale-rotate-transition { + .transition-default(); + + &-enter-from, + &-leave, + &-leave-to { + transform: scale(0) rotate(-45deg); + opacity: 0; + } +} diff --git a/src/design/transition/scroll.less b/src/design/transition/scroll.less new file mode 100644 index 0000000..a5f45e4 --- /dev/null +++ b/src/design/transition/scroll.less @@ -0,0 +1,67 @@ +.scroll-y-transition { + .transition-default(); + + &-enter-from, + &-leave-to { + opacity: 0; + } + + &-enter-from { + transform: translateY(-15px); + } + + &-leave-to { + transform: translateY(15px); + } +} + +.scroll-y-reverse-transition { + .transition-default(); + + &-enter-from, + &-leave-to { + opacity: 0; + } + + &-enter-from { + transform: translateY(15px); + } + + &-leave-to { + transform: translateY(-15px); + } +} + +.scroll-x-transition { + .transition-default(); + + &-enter-from, + &-leave-to { + opacity: 0; + } + + &-enter-from { + transform: translateX(-15px); + } + + &-leave-to { + transform: translateX(15px); + } +} + +.scroll-x-reverse-transition { + .transition-default(); + + &-enter-from, + &-leave-to { + opacity: 0; + } + + &-enter-from { + transform: translateX(15px); + } + + &-leave-to { + transform: translateX(-15px); + } +} diff --git a/src/design/transition/slide.less b/src/design/transition/slide.less new file mode 100644 index 0000000..fe1be22 --- /dev/null +++ b/src/design/transition/slide.less @@ -0,0 +1,39 @@ +.slide-y-transition { + .transition-default(); + + &-enter-from, + &-leave-to { + transform: translateY(-15px); + opacity: 0; + } +} + +.slide-y-reverse-transition { + .transition-default(); + + &-enter-from, + &-leave-to { + transform: translateY(15px); + opacity: 0; + } +} + +.slide-x-transition { + .transition-default(); + + &-enter-from, + &-leave-to { + transform: translateX(-15px); + opacity: 0; + } +} + +.slide-x-reverse-transition { + .transition-default(); + + &-enter-from, + &-leave-to { + transform: translateX(15px); + opacity: 0; + } +} diff --git a/src/design/transition/zoom.less b/src/design/transition/zoom.less new file mode 100644 index 0000000..24ddbb8 --- /dev/null +++ b/src/design/transition/zoom.less @@ -0,0 +1,31 @@ +// zoom-out +.zoom-out-enter-active, +.zoom-out-leave-active { + transition: + opacity 0.1 ease-in-out, + transform 0.15s ease-out; +} + +.zoom-out-enter-from, +.zoom-out-leave-to { + transform: scale(0); + opacity: 0; +} + +// zoom-fade +.zoom-fade-enter-active, +.zoom-fade-leave-active { + transition: + transform 0.2s, + opacity 0.3s ease-out; +} + +.zoom-fade-enter-from { + transform: scale(0.92); + opacity: 0; +} + +.zoom-fade-leave-to { + transform: scale(1.06); + opacity: 0; +} diff --git a/src/design/var/breakpoint.less b/src/design/var/breakpoint.less new file mode 100644 index 0000000..d6fd568 --- /dev/null +++ b/src/design/var/breakpoint.less @@ -0,0 +1,33 @@ +// ================================= +// ==============屏幕断点============ +// ================================= + +// Extra small screen / phone +@screen-xs: 320px; +@screen-xs-min: @screen-xs; + +// Small screen / tablet +@screen-sm: 640px; +@screen-sm-min: @screen-sm; + +// Medium screen / desktop +@screen-md: 768px; +@screen-md-min: @screen-md; + +// Large screen / wide desktop +@screen-lg: 960px; +@screen-lg-min: @screen-lg; + +// Extra large screen / full hd +@screen-xl: 1280px; +@screen-xl-min: @screen-xl; + +// Extra extra large screen / large desktop +@screen-2xl: 1536px; +@screen-2xl-min: @screen-2xl; + +@screen-xs-max: (@screen-sm-min - 1px); +@screen-sm-max: (@screen-md-min - 1px); +@screen-md-max: (@screen-lg-min - 1px); +@screen-lg-max: (@screen-xl-min - 1px); +@screen-xl-max: (@screen-2xl-min - 1px); diff --git a/src/design/var/easing.less b/src/design/var/easing.less new file mode 100644 index 0000000..e19735f --- /dev/null +++ b/src/design/var/easing.less @@ -0,0 +1,18 @@ +// ================================= +// ==============动画函数-=========== +// ================================= + +@ease-base-out: cubic-bezier(0.7, 0.3, 0.1, 1); +@ease-base-in: cubic-bezier(0.9, 0, 0.3, 0.7); +@ease-out: cubic-bezier(0.215, 0.61, 0.355, 1); +@ease-in: cubic-bezier(0.55, 0.055, 0.675, 0.19); +@ease-in-out: cubic-bezier(0.645, 0.045, 0.355, 1); +@ease-out-back: cubic-bezier(0.12, 0.4, 0.29, 1.46); +@ease-in-back: cubic-bezier(0.71, -0.46, 0.88, 0.6); +@ease-in-out-back: cubic-bezier(0.71, -0.46, 0.29, 1.46); +@ease-out-circ: cubic-bezier(0.08, 0.82, 0.17, 1); +@ease-in-circ: cubic-bezier(0.6, 0.04, 0.98, 0.34); +@ease-in-out-circ: cubic-bezier(0.78, 0.14, 0.15, 0.86); +@ease-out-quint: cubic-bezier(0.23, 1, 0.32, 1); +@ease-in-quint: cubic-bezier(0.755, 0.05, 0.855, 0.06); +@ease-in-out-quint: cubic-bezier(0.86, 0, 0.07, 1); diff --git a/src/design/var/index.less b/src/design/var/index.less new file mode 100644 index 0000000..1689f76 --- /dev/null +++ b/src/design/var/index.less @@ -0,0 +1,39 @@ +@import (reference) '../color.less'; +@import 'easing'; +@import 'breakpoint'; + +@namespace: vben; + +// tabs +@multiple-height: 30px; + +// headers +@header-height: 48px; + +// logo width +@logo-width: 32px; + +// +@side-drag-z-index: 200; + +@page-loading-z-index: 10000; + +@lock-page-z-index: 3000; + +@layout-header-fixed-z-index: 500; + +@multiple-tab-fixed-z-index: 505; + +@layout-sider-fixed-z-index: 510; + +@layout-mix-sider-fixed-z-index: 550; + +@preview-comp-z-index: 1000; + +@page-footer-z-index: 99; + +.bem(@n; @content) { + @{namespace}-@{n} { + @content(); + } +} diff --git a/src/directives/clickOutside.ts b/src/directives/clickOutside.ts new file mode 100644 index 0000000..9eedca4 --- /dev/null +++ b/src/directives/clickOutside.ts @@ -0,0 +1,86 @@ +import { on } from '@/utils/domUtils'; +import { isServer } from '@/utils/is'; +import type { ComponentPublicInstance, DirectiveBinding, ObjectDirective } from 'vue'; + +type DocumentHandler = (mouseup: T, mousedown: T) => void; + +type FlushList = Map< + HTMLElement, + { + documentHandler: DocumentHandler; + bindingFn: (...args: unknown[]) => unknown; + } +>; + +const nodeList: FlushList = new Map(); + +let startClick: MouseEvent; + +if (!isServer) { + on(document, 'mousedown', (e: Event) => (startClick = e as MouseEvent)); + on(document, 'mouseup', (e: Event) => { + for (const { documentHandler } of nodeList.values()) { + documentHandler(e as MouseEvent, startClick); + } + }); +} + +function createDocumentHandler(el: HTMLElement, binding: DirectiveBinding): DocumentHandler { + let excludes: HTMLElement[] = []; + if (Array.isArray(binding.arg)) { + excludes = binding.arg; + } else { + // due to current implementation on binding type is wrong the type casting is necessary here + excludes.push(binding.arg as unknown as HTMLElement); + } + return function (mouseup, mousedown) { + const popperRef = ( + binding.instance as ComponentPublicInstance<{ + popperRef: Nullable; + }> + ).popperRef; + const mouseUpTarget = mouseup.target as Node; + const mouseDownTarget = mousedown.target as Node; + const isBound = !binding || !binding.instance; + const isTargetExists = !mouseUpTarget || !mouseDownTarget; + const isContainedByEl = el.contains(mouseUpTarget) || el.contains(mouseDownTarget); + const isSelf = el === mouseUpTarget; + + const isTargetExcluded = + (excludes.length && excludes.some((item) => item?.contains(mouseUpTarget))) || + (excludes.length && excludes.includes(mouseDownTarget as HTMLElement)); + const isContainedByPopper = + popperRef && (popperRef.contains(mouseUpTarget) || popperRef.contains(mouseDownTarget)); + if ( + isBound || + isTargetExists || + isContainedByEl || + isSelf || + isTargetExcluded || + isContainedByPopper + ) { + return; + } + binding.value(); + }; +} + +const ClickOutside: ObjectDirective = { + beforeMount(el, binding) { + nodeList.set(el, { + documentHandler: createDocumentHandler(el, binding), + bindingFn: binding.value, + }); + }, + updated(el, binding) { + nodeList.set(el, { + documentHandler: createDocumentHandler(el, binding), + bindingFn: binding.value, + }); + }, + unmounted(el) { + nodeList.delete(el); + }, +}; + +export default ClickOutside; diff --git a/src/directives/ellipsis.ts b/src/directives/ellipsis.ts new file mode 100644 index 0000000..2370f4e --- /dev/null +++ b/src/directives/ellipsis.ts @@ -0,0 +1,42 @@ +import type { CSSProperties, DirectiveBinding, ObjectDirective, App } from 'vue'; + +interface IValue { + width?: number; + line?: number; +} + +interface IOptions { + [key: string]: CSSProperties; +} + +const cssProperties: IOptions = { + single: { + overflow: 'hidden', + textOverflow: 'ellipsis', + whiteSpace: 'nowrap', + }, + multiple: { + display: '-webkit-box', + overflow: 'hidden', + wordBreak: 'break-all', + }, +}; + +const Ellipsis: ObjectDirective = { + mounted(el: HTMLElement, binding: DirectiveBinding>) { + const { value = [100, 1], arg = 'single' } = binding; + const [width, line] = value; + Object.entries(cssProperties[arg]).forEach(([key, value]) => { + el.style[key] = value; + }); + el.style.width = `${width}px`; + if (arg === 'multiple') { + el.style.webkitLineClamp = `${line}`; + el.style.webkitBoxOrient = 'vertical'; + } + }, +}; +export function setupEllipsisDirective(app: App) { + app.directive('ellipsis', Ellipsis); +} +export default Ellipsis; diff --git a/src/directives/index.ts b/src/directives/index.ts new file mode 100644 index 0000000..ad58631 --- /dev/null +++ b/src/directives/index.ts @@ -0,0 +1,13 @@ +/** + * Configure and register global directives + */ +import type { App } from 'vue'; +import { setupPermissionDirective } from './permission'; +import { setupLoadingDirective } from './loading'; +import { setupEllipsisDirective } from './ellipsis'; + +export function setupGlobDirectives(app: App) { + setupPermissionDirective(app); + setupLoadingDirective(app); + setupEllipsisDirective(app); +} diff --git a/src/directives/loading.ts b/src/directives/loading.ts new file mode 100644 index 0000000..dadb5b7 --- /dev/null +++ b/src/directives/loading.ts @@ -0,0 +1,39 @@ +import { createLoading } from '@/components/Loading'; +import type { Directive, App } from 'vue'; + +const loadingDirective: Directive = { + mounted(el, binding) { + const tip = el.getAttribute('loading-tip'); + const background = el.getAttribute('loading-background'); + const size = el.getAttribute('loading-size'); + const fullscreen = !!binding.modifiers.fullscreen; + const instance = createLoading( + { + tip, + background, + size: size || 'large', + loading: !!binding.value, + absolute: !fullscreen, + }, + fullscreen ? document.body : el, + ); + el.instance = instance; + }, + updated(el, binding) { + const instance = el.instance; + if (!instance) return; + instance.setTip(el.getAttribute('loading-tip')); + if (binding.oldValue !== binding.value) { + instance.setLoading?.(binding.value && !instance.loading); + } + }, + unmounted(el) { + el?.instance?.close(); + }, +}; + +export function setupLoadingDirective(app: App) { + app.directive('loading', loadingDirective); +} + +export default loadingDirective; diff --git a/src/directives/permission.ts b/src/directives/permission.ts new file mode 100644 index 0000000..319e340 --- /dev/null +++ b/src/directives/permission.ts @@ -0,0 +1,32 @@ +/** + * Global authority directive + * Used for fine-grained control of component permissions + * @Example v-auth="RoleEnum.TEST" + */ +import type { App, Directive, DirectiveBinding } from 'vue'; + +import { usePermission } from '@/hooks/web/usePermission'; + +function isAuth(el: Element, binding: any) { + const { hasPermission } = usePermission(); + + const value = binding.value; + if (!value) return; + if (!hasPermission(value)) { + el.parentNode?.removeChild(el); + } +} + +const mounted = (el: Element, binding: DirectiveBinding) => { + isAuth(el, binding); +}; + +const authDirective: Directive = { + mounted, +}; + +export function setupPermissionDirective(app: App) { + app.directive('auth', authDirective); +} + +export default authDirective; diff --git a/src/directives/repeatClick.ts b/src/directives/repeatClick.ts new file mode 100644 index 0000000..bb28921 --- /dev/null +++ b/src/directives/repeatClick.ts @@ -0,0 +1,31 @@ +/** + * Prevent repeated clicks + * @Example v-repeat-click="()=>{}" + */ +import { on, once } from '@/utils/domUtils'; +import type { Directive, DirectiveBinding } from 'vue'; + +const repeatDirective: Directive = { + beforeMount(el: Element, binding: DirectiveBinding) { + let interval: Nullable = null; + let startTime = 0; + const handler = (): void => binding?.value(); + const clear = (): void => { + if (Date.now() - startTime < 100) { + handler(); + } + interval && clearInterval(interval); + interval = null; + }; + + on(el, 'mousedown', (e: Event): void => { + if ((e as MouseEvent).button !== 0) return; + startTime = Date.now(); + once(document as any, 'mouseup', clear); + interval && clearInterval(interval); + interval = setInterval(handler, 100); + }); + }, +}; + +export default repeatDirective; diff --git a/src/directives/ripple/index.less b/src/directives/ripple/index.less new file mode 100644 index 0000000..70a1c3f --- /dev/null +++ b/src/directives/ripple/index.less @@ -0,0 +1,21 @@ +.ripple-container { + position: absolute; + top: 0; + left: 0; + width: 0; + height: 0; + overflow: hidden; + pointer-events: none; +} + +.ripple-effect { + position: relative; + z-index: 9999; + width: 1px; + height: 1px; + margin-top: 0; + margin-left: 0; + transition: all 0.6s cubic-bezier(0.4, 0, 0.2, 1); + border-radius: 50%; + pointer-events: none; +} diff --git a/src/directives/ripple/index.ts b/src/directives/ripple/index.ts new file mode 100644 index 0000000..d256497 --- /dev/null +++ b/src/directives/ripple/index.ts @@ -0,0 +1,192 @@ +import type { Directive } from 'vue'; +import './index.less'; + +export interface RippleOptions { + event: string; + transition: number; +} + +export interface RippleProto { + background?: string; + zIndex?: string; +} + +export type EventType = Event & MouseEvent & TouchEvent; + +const options: RippleOptions = { + event: 'mousedown', + transition: 400, +}; + +const RippleDirective: Directive & RippleProto = { + beforeMount: (el: HTMLElement, binding) => { + if (binding.value === false) return; + + const bg = el.getAttribute('ripple-background'); + setProps(Object.keys(binding.modifiers), options); + + const background = bg || RippleDirective.background; + const zIndex = RippleDirective.zIndex; + + el.addEventListener(options.event, (event: Event) => { + rippler({ + event: event as EventType, + el, + background, + zIndex, + }); + }); + }, + updated(el, binding) { + if (!binding.value) { + el?.clearRipple?.(); + return; + } + const bg = el.getAttribute('ripple-background'); + el?.setBackground?.(bg); + }, +}; + +function rippler({ + event, + el, + zIndex, + background, +}: { event: EventType; el: HTMLElement } & RippleProto) { + const targetBorder = parseInt(getComputedStyle(el).borderWidth.replace('px', '')); + const clientX = event.clientX || event.touches[0].clientX; + const clientY = event.clientY || event.touches[0].clientY; + + const rect = el.getBoundingClientRect(); + const { left, top } = rect; + const { offsetWidth: width, offsetHeight: height } = el; + const { transition } = options; + const dx = clientX - left; + const dy = clientY - top; + const maxX = Math.max(dx, width - dx); + const maxY = Math.max(dy, height - dy); + const style = window.getComputedStyle(el); + const radius = Math.sqrt(maxX * maxX + maxY * maxY); + const border = targetBorder > 0 ? targetBorder : 0; + + const ripple = document.createElement('div'); + const rippleContainer = document.createElement('div'); + + // Styles for ripple + ripple.className = 'ripple'; + + Object.assign(ripple.style ?? {}, { + marginTop: '0px', + marginLeft: '0px', + width: '1px', + height: '1px', + transition: `all ${transition}ms cubic-bezier(0.4, 0, 0.2, 1)`, + borderRadius: '50%', + pointerEvents: 'none', + position: 'relative', + zIndex: zIndex ?? '9999', + backgroundColor: background ?? 'rgba(0, 0, 0, 0.12)', + }); + + // Styles for rippleContainer + rippleContainer.className = 'ripple-container'; + Object.assign(rippleContainer.style ?? {}, { + position: 'absolute', + left: `${0 - border}px`, + top: `${0 - border}px`, + height: '0', + width: '0', + pointerEvents: 'none', + overflow: 'hidden', + }); + + const storedTargetPosition = + el.style.position.length > 0 ? el.style.position : getComputedStyle(el).position; + + if (storedTargetPosition !== 'relative') { + el.style.position = 'relative'; + } + + rippleContainer.appendChild(ripple); + el.appendChild(rippleContainer); + + Object.assign(ripple.style, { + marginTop: `${dy}px`, + marginLeft: `${dx}px`, + }); + + const { + borderTopLeftRadius, + borderTopRightRadius, + borderBottomLeftRadius, + borderBottomRightRadius, + } = style; + Object.assign(rippleContainer.style, { + width: `${width}px`, + height: `${height}px`, + direction: 'ltr', + borderTopLeftRadius, + borderTopRightRadius, + borderBottomLeftRadius, + borderBottomRightRadius, + }); + + setTimeout(() => { + const wh = `${radius * 2}px`; + Object.assign(ripple.style ?? {}, { + width: wh, + height: wh, + marginLeft: `${dx - radius}px`, + marginTop: `${dy - radius}px`, + }); + }, 0); + + function clearRipple() { + setTimeout(() => { + ripple.style.backgroundColor = 'rgba(0, 0, 0, 0)'; + }, 250); + + setTimeout(() => { + rippleContainer?.parentNode?.removeChild(rippleContainer); + }, 850); + el.removeEventListener('mouseup', clearRipple, false); + el.removeEventListener('mouseleave', clearRipple, false); + el.removeEventListener('dragstart', clearRipple, false); + setTimeout(() => { + let clearPosition = true; + for (let i = 0; i < el.childNodes.length; i++) { + if ((el.childNodes[i] as Recordable).className === 'ripple-container') { + clearPosition = false; + } + } + + if (clearPosition) { + el.style.position = storedTargetPosition !== 'static' ? storedTargetPosition : ''; + } + }, options.transition + 260); + } + + if (event.type === 'mousedown') { + el.addEventListener('mouseup', clearRipple, false); + el.addEventListener('mouseleave', clearRipple, false); + el.addEventListener('dragstart', clearRipple, false); + } else { + clearRipple(); + } + + (el as Recordable).setBackground = (bgColor: string) => { + if (!bgColor) { + return; + } + ripple.style.backgroundColor = bgColor; + }; +} + +function setProps(modifiers: Recordable, props: Recordable) { + modifiers.forEach((item: Recordable) => { + if (isNaN(Number(item))) props.event = item; + else props.transition = item; + }); +} + +export default RippleDirective; diff --git a/src/enums/ImageEnum.ts b/src/enums/ImageEnum.ts new file mode 100644 index 0000000..149c852 --- /dev/null +++ b/src/enums/ImageEnum.ts @@ -0,0 +1,17 @@ +export enum ImageEnum { + + WEI_FA_YONG_DI = "违法用地", + + FEI_FA_CAI_KUANG_WEI_PIAN_XIA_FA = '非法采矿卫片下发', + + FEI_FA_CAI_KUANG_GONGZUOGUANLI = '非法采矿工作管理', + + GENG_DI_FEI_LIANG_HUA = '耕地非粮化', + + ZHONG_DIAN_WEN_TI_1 = '重点问题1类', + + ZHONG_DIAN_WEN_TI_2 = '重点问题2类', + + XUN_CHA_SHEN_JI = '巡察审计', + +} \ No newline at end of file diff --git a/src/enums/appEnum.ts b/src/enums/appEnum.ts new file mode 100644 index 0000000..1fc3989 --- /dev/null +++ b/src/enums/appEnum.ts @@ -0,0 +1,52 @@ +export const SIDE_BAR_MINI_WIDTH = 48; +export const SIDE_BAR_SHOW_TIT_MINI_WIDTH = 80; + +export enum ContentEnum { + // auto width + FULL = 'full', + // fixed width + FIXED = 'fixed', +} + +// menu theme enum +export enum ThemeEnum { + DARK = 'dark', + LIGHT = 'light', +} + +export enum SettingButtonPositionEnum { + AUTO = 'auto', + HEADER = 'header', + FIXED = 'fixed', +} + +export enum SessionTimeoutProcessingEnum { + ROUTE_JUMP, + PAGE_COVERAGE, +} + +/** + * 权限模式 + */ +export enum PermissionModeEnum { + // role + // 角色权限 + ROLE = 'ROLE', + // black + // 后端 + BACK = 'BACK', + // route mapping + // 路由映射 + ROUTE_MAPPING = 'ROUTE_MAPPING', +} + +// Route switching animation +// 路由切换动画 +export enum RouterTransitionEnum { + ZOOM_FADE = 'zoom-fade', + ZOOM_OUT = 'zoom-out', + FADE_SIDE = 'fade-slide', + FADE = 'fade', + FADE_BOTTOM = 'fade-bottom', + FADE_SCALE = 'fade-scale', +} diff --git a/src/enums/breakpointEnum.ts b/src/enums/breakpointEnum.ts new file mode 100644 index 0000000..f741d1a --- /dev/null +++ b/src/enums/breakpointEnum.ts @@ -0,0 +1,28 @@ +export enum sizeEnum { + XS = 'XS', + SM = 'SM', + MD = 'MD', + LG = 'LG', + XL = 'XL', + XXL = 'XXL', +} + +export enum screenEnum { + XS = 320, + SM = 640, + MD = 768, + LG = 960, + XL = 1280, + XXL = 1536, +} + +const screenMap = new Map(); + +screenMap.set(sizeEnum.XS, screenEnum.XS); +screenMap.set(sizeEnum.SM, screenEnum.SM); +screenMap.set(sizeEnum.MD, screenEnum.MD); +screenMap.set(sizeEnum.LG, screenEnum.LG); +screenMap.set(sizeEnum.XL, screenEnum.XL); +screenMap.set(sizeEnum.XXL, screenEnum.XXL); + +export { screenMap }; diff --git a/src/enums/cacheEnum.ts b/src/enums/cacheEnum.ts new file mode 100644 index 0000000..eb26c85 --- /dev/null +++ b/src/enums/cacheEnum.ts @@ -0,0 +1,40 @@ +// token key +export const TOKEN_KEY = 'TOKEN__'; + +export const LOCALE_KEY = 'LOCALE__'; + +// user info key +export const USER_INFO_KEY = 'USER__INFO__'; + +// role info key +export const ROLES_KEY = 'ROLES__KEY__'; + +// project config key +export const PROJ_CFG_KEY = 'PROJ__CFG__KEY__'; +export const API_ADDRESS = 'API_ADDRESS__'; + +// lock info +export const LOCK_INFO_KEY = 'LOCK__INFO__KEY__'; + +export const MULTIPLE_TABS_KEY = 'MULTIPLE_TABS__KEY__'; + +export const APP_DARK_MODE_KEY = '__APP__DARK__MODE__'; + +// base global local key +export const APP_LOCAL_CACHE_KEY = 'COMMON__LOCAL__KEY__'; + +// base global session key +export const APP_SESSION_CACHE_KEY = 'COMMON__SESSION__KEY__'; + +// table 列设置 +export const TABLE_SETTING_KEY = 'TABLE__SETTING__KEY__'; + +// 专题设置 +export const SUBJECT_KEY = 'SUBJECT__'; +export const SUBJECT_TITLE = 'SUBJECT_TITLE__'; +export const SUBJECT_LOGO_TITLE = 'SUBJECT_LOGO_TITLE__'; + +export enum CacheTypeEnum { + SESSION, + LOCAL, +} diff --git a/src/enums/exceptionEnum.ts b/src/enums/exceptionEnum.ts new file mode 100644 index 0000000..d28f4d0 --- /dev/null +++ b/src/enums/exceptionEnum.ts @@ -0,0 +1,27 @@ +/** + * @description: Exception related enumeration + */ +export enum ExceptionEnum { + // page not access + PAGE_NOT_ACCESS = 403, + + // page not found + PAGE_NOT_FOUND = 404, + + // error + ERROR = 500, + + // net work error + NET_WORK_ERROR = 10000, + + // No data on the page. In fact, it is not an exception page + PAGE_NOT_DATA = 10100, +} + +export enum ErrorTypeEnum { + VUE = 'vue', + SCRIPT = 'script', + RESOURCE = 'resource', + AJAX = 'ajax', + PROMISE = 'promise', +} diff --git a/src/enums/httpEnum.ts b/src/enums/httpEnum.ts new file mode 100644 index 0000000..6c9f357 --- /dev/null +++ b/src/enums/httpEnum.ts @@ -0,0 +1,31 @@ +/** + * @description: Request result set + */ +export enum ResultEnum { + SUCCESS = 200, + ERROR = -1, + TIMEOUT = 401, + TYPE = 'success', +} + +/** + * @description: request method + */ +export enum RequestEnum { + GET = 'GET', + POST = 'POST', + PUT = 'PUT', + DELETE = 'DELETE', +} + +/** + * @description: contentType + */ +export enum ContentTypeEnum { + // json + JSON = 'application/json;charset=UTF-8', + // form-data qs + FORM_URLENCODED = 'application/x-www-form-urlencoded;charset=UTF-8', + // form-data upload + FORM_DATA = 'multipart/form-data;charset=UTF-8', +} diff --git a/src/enums/mapEnum.ts b/src/enums/mapEnum.ts new file mode 100644 index 0000000..189f602 --- /dev/null +++ b/src/enums/mapEnum.ts @@ -0,0 +1,5 @@ +export enum DrawingType { + Point = 'DrawPoint', + Line = 'DrawLineString', + Polygon = 'DrawPolygon', +} diff --git a/src/enums/menuEnum.ts b/src/enums/menuEnum.ts new file mode 100644 index 0000000..89cfa9f --- /dev/null +++ b/src/enums/menuEnum.ts @@ -0,0 +1,50 @@ +/** + * @description: menu type + */ +export enum MenuTypeEnum { + // left menu + SIDEBAR = 'sidebar', + + MIX_SIDEBAR = 'mix-sidebar', + // mixin menu + MIX = 'mix', + // top menu + TOP_MENU = 'top-menu', +} + +// 折叠触发器位置 +export enum TriggerEnum { + // 不显示 + NONE = 'NONE', + // 菜单底部 + FOOTER = 'FOOTER', + // 头部 + HEADER = 'HEADER', +} + +export type Mode = 'vertical' | 'vertical-right' | 'horizontal' | 'inline'; + +// menu mode +export enum MenuModeEnum { + VERTICAL = 'vertical', + HORIZONTAL = 'horizontal', + VERTICAL_RIGHT = 'vertical-right', + INLINE = 'inline', +} + +export enum MenuSplitTyeEnum { + NONE, + TOP, + LEFT, +} + +export enum TopMenuAlignEnum { + CENTER = 'center', + START = 'start', + END = 'end', +} + +export enum MixSidebarTriggerEnum { + HOVER = 'hover', + CLICK = 'click', +} diff --git a/src/enums/pageEnum.ts b/src/enums/pageEnum.ts new file mode 100644 index 0000000..9b8dbf1 --- /dev/null +++ b/src/enums/pageEnum.ts @@ -0,0 +1,13 @@ +export enum PageEnum { + // basic login path + BASE_LOGIN = '/login', + // basic home path + BASE_HOME = '/dashboard', + // error page path + ERROR_PAGE = '/exception', + // error log page path + ERROR_LOG_PAGE = '/error-log/list', + // 欢迎登陆 + WELCOME_HOME = '/welcome', +} +export const PageWrapperFixedHeightKey = 'PageWrapperFixedHeight'; diff --git a/src/enums/roleEnum.ts b/src/enums/roleEnum.ts new file mode 100644 index 0000000..857868d --- /dev/null +++ b/src/enums/roleEnum.ts @@ -0,0 +1,7 @@ +export enum RoleEnum { + // super admin + SUPER = 'super', + + // tester + TEST = 'test', +} diff --git a/src/enums/sizeEnum.ts b/src/enums/sizeEnum.ts new file mode 100644 index 0000000..cbbc152 --- /dev/null +++ b/src/enums/sizeEnum.ts @@ -0,0 +1,5 @@ +export enum SizeEnum { + DEFAULT = 'default', + SMALL = 'small', + LARGE = 'large', +} diff --git a/src/env.d.ts b/src/env.d.ts new file mode 100644 index 0000000..13a865f --- /dev/null +++ b/src/env.d.ts @@ -0,0 +1,6 @@ +declare module '*.vue' { + import type { DefineComponent } from 'vue'; + // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/ban-types + const component: DefineComponent<{}, {}, any>; + export default component; +} diff --git a/src/hooks/component/useFormItem.ts b/src/hooks/component/useFormItem.ts new file mode 100644 index 0000000..fbd7037 --- /dev/null +++ b/src/hooks/component/useFormItem.ts @@ -0,0 +1,60 @@ +import type { UnwrapRef, Ref, WritableComputedRef, DeepReadonly } from 'vue'; +import { + reactive, + readonly, + computed, + getCurrentInstance, + watchEffect, + unref, + toRaw, + nextTick, +} from 'vue'; + +import { isEqual } from 'lodash-es'; + +export function useRuleFormItem>( + props: T, + key?: K, + changeEvent?, + emitData?: Ref, +): [WritableComputedRef, (val: V) => void, DeepReadonly]; + +export function useRuleFormItem( + props: T, + key: keyof T = 'value', + changeEvent = 'change', + emitData?: Ref, +) { + const instance = getCurrentInstance(); + const emit = instance?.emit; + + const innerState = reactive({ + value: props[key], + }); + + const defaultState = readonly(innerState); + + const setState = (val: UnwrapRef): void => { + innerState.value = val as T[keyof T]; + }; + + watchEffect(() => { + innerState.value = props[key]; + }); + + const state: any = computed({ + get() { + return innerState.value; + }, + set(value) { + if (isEqual(value, defaultState.value)) return; + + innerState.value = value as T[keyof T]; + nextTick(() => { + emit?.(changeEvent, value, ...(toRaw(unref(emitData)) || [])); + }); + }, + }); + + return [state, setState, defaultState]; +} diff --git a/src/hooks/component/usePageContext.ts b/src/hooks/component/usePageContext.ts new file mode 100644 index 0000000..1e2e715 --- /dev/null +++ b/src/hooks/component/usePageContext.ts @@ -0,0 +1,18 @@ +import type { InjectionKey, ComputedRef, Ref } from 'vue'; +import { createContext, useContext } from '@/hooks/core/useContext'; + +export interface PageContextProps { + contentHeight: ComputedRef; + pageHeight: Ref; + setPageHeight: (height: number) => Promise; +} + +const key: InjectionKey = Symbol(); + +export function createPageContext(context: PageContextProps) { + return createContext(context, key, { native: true }); +} + +export function usePageContext() { + return useContext(key); +} diff --git a/src/hooks/core/useContext.ts b/src/hooks/core/useContext.ts new file mode 100644 index 0000000..04a9433 --- /dev/null +++ b/src/hooks/core/useContext.ts @@ -0,0 +1,43 @@ +import { + InjectionKey, + provide, + inject, + reactive, + readonly as defineReadonly, + UnwrapRef, +} from 'vue'; + +export interface CreateContextOptions { + readonly?: boolean; + createProvider?: boolean; + native?: boolean; +} + +type ShallowUnwrap = { + [P in keyof T]: UnwrapRef; +}; + +export function createContext( + context: any, + key: InjectionKey = Symbol(), + options: CreateContextOptions = {}, +) { + const { readonly = true, createProvider = true, native = false } = options; + + const state = reactive(context); + const provideData = readonly ? defineReadonly(state) : state; + createProvider && provide(key, native ? context : provideData); + + return { + state, + }; +} + +export function useContext(key: InjectionKey, native?: boolean): T; + +export function useContext( + key: InjectionKey = Symbol(), + defaultValue?: any, +): ShallowUnwrap { + return inject(key, defaultValue || {}); +} diff --git a/src/hooks/event/useBreakpoint.ts b/src/hooks/event/useBreakpoint.ts new file mode 100644 index 0000000..b51b03e --- /dev/null +++ b/src/hooks/event/useBreakpoint.ts @@ -0,0 +1,93 @@ +import { ref, computed, ComputedRef, unref } from 'vue'; +import { useEventListener } from '@/hooks/event/useEventListener'; +import { screenMap, sizeEnum, screenEnum } from '@/enums/breakpointEnum'; + +// 可以用这个替换,优化项 +// import { Grid } from 'ant-design-vue'; +// const { useBreakpoint } = Grid; + +let globalScreenRef: ComputedRef; +let globalWidthRef: ComputedRef; +let globalRealWidthRef: ComputedRef; + +export interface CreateCallbackParams { + screen: ComputedRef; + width: ComputedRef; + realWidth: ComputedRef; + screenEnum: typeof screenEnum; + screenMap: Map; + sizeEnum: typeof sizeEnum; +} + +export function useBreakpoint() { + return { + screenRef: computed(() => unref(globalScreenRef)), + widthRef: globalWidthRef, + screenEnum, + realWidthRef: globalRealWidthRef, + }; +} + +// Just call it once +export function createBreakpointListen(fn?: (opt: CreateCallbackParams) => void) { + const screenRef = ref(sizeEnum.XL); + const realWidthRef = ref(window.innerWidth); + + function getWindowWidth() { + const width = document.body.clientWidth; + const xs = screenMap.get(sizeEnum.XS)!; + const sm = screenMap.get(sizeEnum.SM)!; + const md = screenMap.get(sizeEnum.MD)!; + const lg = screenMap.get(sizeEnum.LG)!; + const xl = screenMap.get(sizeEnum.XL)!; + if (width < xs) { + screenRef.value = sizeEnum.XS; + } else if (width < sm) { + screenRef.value = sizeEnum.SM; + } else if (width < md) { + screenRef.value = sizeEnum.MD; + } else if (width < lg) { + screenRef.value = sizeEnum.LG; + } else if (width < xl) { + screenRef.value = sizeEnum.XL; + } else { + screenRef.value = sizeEnum.XXL; + } + realWidthRef.value = width; + } + + useEventListener({ + el: window, + name: 'resize', + + listener: () => { + getWindowWidth(); + resizeFn(); + }, + // wait: 100, + }); + + getWindowWidth(); + globalScreenRef = computed(() => unref(screenRef)); + globalWidthRef = computed((): number => screenMap.get(unref(screenRef)!)!); + globalRealWidthRef = computed((): number => unref(realWidthRef)); + + function resizeFn() { + fn?.({ + screen: globalScreenRef, + width: globalWidthRef, + realWidth: globalRealWidthRef, + screenEnum, + screenMap, + sizeEnum, + }); + } + + resizeFn(); + return { + screenRef: globalScreenRef, + screenEnum, + widthRef: globalWidthRef, + realWidthRef: globalRealWidthRef, + }; +} diff --git a/src/hooks/event/useEventListener.ts b/src/hooks/event/useEventListener.ts new file mode 100644 index 0000000..892cd92 --- /dev/null +++ b/src/hooks/event/useEventListener.ts @@ -0,0 +1,58 @@ +import type { Ref } from 'vue'; +import { ref, watch, unref } from 'vue'; +import { useThrottleFn, useDebounceFn } from '@vueuse/core'; + +export type RemoveEventFn = () => void; +export interface UseEventParams { + el?: Element | Ref | Window | any; + name: string; + listener: EventListener; + options?: boolean | AddEventListenerOptions; + autoRemove?: boolean; + isDebounce?: boolean; + wait?: number; +} +export function useEventListener({ + el = window, + name, + listener, + options, + autoRemove = true, + isDebounce = true, + wait = 80, +}: UseEventParams): { removeEvent: RemoveEventFn } { + /* eslint-disable-next-line */ + let remove: RemoveEventFn = () => {}; + const isAddRef = ref(false); + + if (el) { + const element = ref(el as Element) as Ref; + + const handler = isDebounce ? useDebounceFn(listener, wait) : useThrottleFn(listener, wait); + const realHandler = wait ? handler : listener; + const removeEventListener = (e: Element) => { + isAddRef.value = true; + e.removeEventListener(name, realHandler, options); + }; + const addEventListener = (e: Element) => e.addEventListener(name, realHandler, options); + + const removeWatch = watch( + element, + (v, _ov, cleanUp) => { + if (v) { + !unref(isAddRef) && addEventListener(v); + cleanUp(() => { + autoRemove && removeEventListener(v); + }); + } + }, + { immediate: true }, + ); + + remove = () => { + removeEventListener(element.value); + removeWatch(); + }; + } + return { removeEvent: remove }; +} diff --git a/src/hooks/event/useScroll.ts b/src/hooks/event/useScroll.ts new file mode 100644 index 0000000..0827120 --- /dev/null +++ b/src/hooks/event/useScroll.ts @@ -0,0 +1,65 @@ +import type { Ref } from 'vue'; + +import { ref, onMounted, watch, onUnmounted } from 'vue'; +import { isWindow, isObject } from '@/utils/is'; +import { useThrottleFn } from '@vueuse/core'; + +export function useScroll( + refEl: Ref, + options?: { + wait?: number; + leading?: boolean; + trailing?: boolean; + }, +) { + const refX = ref(0); + const refY = ref(0); + let handler = () => { + if (isWindow(refEl.value)) { + refX.value = refEl.value.scrollX; + refY.value = refEl.value.scrollY; + } else if (refEl.value) { + refX.value = (refEl.value as Element).scrollLeft; + refY.value = (refEl.value as Element).scrollTop; + } + }; + + if (isObject(options)) { + let wait = 0; + if (options.wait && options.wait > 0) { + wait = options.wait; + Reflect.deleteProperty(options, 'wait'); + } + + handler = useThrottleFn(handler, wait); + } + + let stopWatch: () => void; + onMounted(() => { + stopWatch = watch( + refEl, + (el, prevEl, onCleanup) => { + if (el) { + el.addEventListener('scroll', handler); + } else if (prevEl) { + prevEl.removeEventListener('scroll', handler); + } + onCleanup(() => { + refX.value = refY.value = 0; + el && el.removeEventListener('scroll', handler); + }); + }, + { immediate: true }, + ); + }); + + onUnmounted(() => { + refEl.value && refEl.value.removeEventListener('scroll', handler); + }); + + function stop() { + stopWatch && stopWatch(); + } + + return { refX, refY, stop }; +} diff --git a/src/hooks/setting/index.ts b/src/hooks/setting/index.ts new file mode 100644 index 0000000..59326f3 --- /dev/null +++ b/src/hooks/setting/index.ts @@ -0,0 +1,18 @@ +import type { GlobConfig } from '#/config'; + +import { getAppEnvConfig } from '@/utils/env'; + +export const useGlobSetting = (): Readonly => { + const { VITE_GLOB_APP_TITLE, VITE_GLOB_API_URL, VITE_GLOB_API_URL_PREFIX, VITE_GLOB_UPLOAD_URL } = + getAppEnvConfig(); + + // Take global configuration + const glob: Readonly = { + title: VITE_GLOB_APP_TITLE, + apiUrl: VITE_GLOB_API_URL, + shortName: VITE_GLOB_APP_TITLE.replace(/\s/g, '_').replace(/-/g, '_'), + urlPrefix: VITE_GLOB_API_URL_PREFIX, + uploadUrl: VITE_GLOB_UPLOAD_URL, + }; + return glob as Readonly; +}; diff --git a/src/hooks/setting/useDarkModeTheme.ts b/src/hooks/setting/useDarkModeTheme.ts new file mode 100644 index 0000000..157c496 --- /dev/null +++ b/src/hooks/setting/useDarkModeTheme.ts @@ -0,0 +1,18 @@ +import { computed } from 'vue'; +import { theme } from 'ant-design-vue'; +import { useRootSetting } from '@/hooks/setting/useRootSetting'; +import { ThemeEnum } from '@/enums/appEnum'; + +export function useDarkModeTheme() { + const { getDarkMode } = useRootSetting(); + const { darkAlgorithm } = theme; + const isDark = computed(() => getDarkMode.value === ThemeEnum.DARK); + const darkTheme = { + algorithm: [darkAlgorithm], + }; + + return { + isDark, + darkTheme, + }; +} diff --git a/src/hooks/setting/useHeaderSetting.ts b/src/hooks/setting/useHeaderSetting.ts new file mode 100644 index 0000000..54993ef --- /dev/null +++ b/src/hooks/setting/useHeaderSetting.ts @@ -0,0 +1,108 @@ +import type { HeaderSetting } from '#/config'; + +import { computed, unref } from 'vue'; + +import { useAppStore } from '@/store/modules/app'; + +import { useMenuSetting } from '@/hooks/setting/useMenuSetting'; +import { useRootSetting } from '@/hooks/setting/useRootSetting'; +import { useFullContent } from '@/hooks/web/useFullContent'; +import { MenuModeEnum } from '@/enums/menuEnum'; + +export function useHeaderSetting() { + const { getFullContent } = useFullContent(); + const appStore = useAppStore(); + + const getShowFullHeaderRef = computed(() => { + return ( + !unref(getFullContent) && + unref(getShowMixHeaderRef) && + unref(getShowHeader) && + !unref(getIsTopMenu) && + !unref(getIsMixSidebar) + ); + }); + + const getUnFixedAndFull = computed(() => !unref(getFixed) && !unref(getShowFullHeaderRef)); + + const getShowInsetHeaderRef = computed(() => { + const need = !unref(getFullContent) && unref(getShowHeader); + return ( + (need && !unref(getShowMixHeaderRef)) || + (need && unref(getIsTopMenu)) || + (need && unref(getIsMixSidebar)) + ); + }); + + const { + getMenuMode, + getSplit, + getShowHeaderTrigger, + getIsSidebarType, + getIsMixSidebar, + getIsTopMenu, + } = useMenuSetting(); + const { getShowBreadCrumb, getShowLogo } = useRootSetting(); + + const getShowMixHeaderRef = computed(() => !unref(getIsSidebarType) && unref(getShowHeader)); + + const getShowDoc = computed(() => appStore.getHeaderSetting.showDoc); + + const getShowApi = computed(() => appStore.getHeaderSetting.showApi); + + const getHeaderTheme = computed(() => appStore.getHeaderSetting.theme); + + const getShowHeader = computed(() => appStore.getHeaderSetting.show); + + const getFixed = computed(() => appStore.getHeaderSetting.fixed); + + const getHeaderBgColor = computed(() => appStore.getHeaderSetting.bgColor); + + const getShowSearch = computed(() => appStore.getHeaderSetting.showSearch); + + const getUseLockPage = computed(() => appStore.getHeaderSetting.useLockPage); + + const getShowFullScreen = computed(() => appStore.getHeaderSetting.showFullScreen); + + const getShowNotice = computed(() => appStore.getHeaderSetting.showNotice); + + const getShowBread = computed(() => { + return ( + unref(getMenuMode) !== MenuModeEnum.HORIZONTAL && unref(getShowBreadCrumb) && !unref(getSplit) + ); + }); + + const getShowHeaderLogo = computed(() => { + return unref(getShowLogo) && !unref(getIsSidebarType) && !unref(getIsMixSidebar); + }); + + const getShowContent = computed(() => { + return unref(getShowBread) || unref(getShowHeaderTrigger); + }); + + // Set header configuration + function setHeaderSetting(headerSetting: Partial) { + appStore.setProjectConfig({ headerSetting }); + } + return { + setHeaderSetting, + + getShowDoc, + getShowApi, + getShowSearch, + getHeaderTheme, + getUseLockPage, + getShowFullScreen, + getShowNotice, + getShowBread, + getShowContent, + getShowHeaderLogo, + getShowHeader, + getFixed, + getShowMixHeaderRef, + getShowFullHeaderRef, + getShowInsetHeaderRef, + getUnFixedAndFull, + getHeaderBgColor, + }; +} diff --git a/src/hooks/setting/useMenuSetting.ts b/src/hooks/setting/useMenuSetting.ts new file mode 100644 index 0000000..173c254 --- /dev/null +++ b/src/hooks/setting/useMenuSetting.ts @@ -0,0 +1,168 @@ +import type { MenuSetting } from '#/config'; + +import { computed, unref, ref } from 'vue'; + +import { useAppStore } from '@/store/modules/app'; + +import { SIDE_BAR_MINI_WIDTH, SIDE_BAR_SHOW_TIT_MINI_WIDTH } from '@/enums/appEnum'; +import { MenuModeEnum, MenuTypeEnum, TriggerEnum } from '@/enums/menuEnum'; +import { useFullContent } from '@/hooks/web/useFullContent'; + +const mixSideHasChildren = ref(false); + +export function useMenuSetting() { + const { getFullContent: fullContent } = useFullContent(); + const appStore = useAppStore(); + + const getShowSidebar = computed(() => { + return ( + unref(getSplit) || + (unref(getShowMenu) && unref(getMenuMode) !== MenuModeEnum.HORIZONTAL && !unref(fullContent)) + ); + }); + + const getCollapsed = computed(() => appStore.getMenuSetting.collapsed); + + const getMenuType = computed(() => appStore.getMenuSetting.type); + + const getMenuMode = computed(() => appStore.getMenuSetting.mode); + + const getMenuFixed = computed(() => appStore.getMenuSetting.fixed); + + const getShowMenu = computed(() => appStore.getMenuSetting.show); + + const getMenuHidden = computed(() => appStore.getMenuSetting.hidden); + + const getMenuWidth = computed(() => appStore.getMenuSetting.menuWidth); + + const getTrigger = computed(() => appStore.getMenuSetting.trigger); + + const getMenuTheme = computed(() => appStore.getMenuSetting.theme); + + const getSplit = computed(() => appStore.getMenuSetting.split); + + const getMenuBgColor = computed(() => appStore.getMenuSetting.bgColor); + + const getMixSideTrigger = computed(() => appStore.getMenuSetting.mixSideTrigger); + + const getCanDrag = computed(() => appStore.getMenuSetting.canDrag); + + const getAccordion = computed(() => appStore.getMenuSetting.accordion); + + const getMixSideFixed = computed(() => appStore.getMenuSetting.mixSideFixed); + + const getTopMenuAlign = computed(() => appStore.getMenuSetting.topMenuAlign); + + const getCloseMixSidebarOnChange = computed( + () => appStore.getMenuSetting.closeMixSidebarOnChange, + ); + + const getIsSidebarType = computed(() => unref(getMenuType) === MenuTypeEnum.SIDEBAR); + + const getIsTopMenu = computed(() => unref(getMenuType) === MenuTypeEnum.TOP_MENU); + + const getCollapsedShowTitle = computed(() => appStore.getMenuSetting.collapsedShowTitle); + + const getShowTopMenu = computed(() => { + return unref(getMenuMode) === MenuModeEnum.HORIZONTAL || unref(getSplit); + }); + + const getShowHeaderTrigger = computed(() => { + if ( + unref(getMenuType) === MenuTypeEnum.TOP_MENU || + !unref(getShowMenu) || + unref(getMenuHidden) + ) { + return false; + } + + return unref(getTrigger) === TriggerEnum.HEADER; + }); + + const getIsHorizontal = computed(() => { + return unref(getMenuMode) === MenuModeEnum.HORIZONTAL; + }); + + const getIsMixSidebar = computed(() => { + return unref(getMenuType) === MenuTypeEnum.MIX_SIDEBAR; + }); + + const getIsMixMode = computed(() => { + return unref(getMenuMode) === MenuModeEnum.INLINE && unref(getMenuType) === MenuTypeEnum.MIX; + }); + + const getRealWidth = computed(() => { + if (unref(getIsMixSidebar)) { + return unref(getCollapsed) && !unref(getMixSideFixed) + ? unref(getMiniWidthNumber) + : unref(getMenuWidth); + } + return unref(getCollapsed) ? unref(getMiniWidthNumber) : unref(getMenuWidth); + }); + + const getMiniWidthNumber = computed(() => { + const { collapsedShowTitle, siderHidden } = appStore.getMenuSetting; + return siderHidden + ? 0 + : collapsedShowTitle + ? SIDE_BAR_SHOW_TIT_MINI_WIDTH + : SIDE_BAR_MINI_WIDTH; + }); + + const getCalcContentWidth = computed(() => { + const width = + unref(getIsTopMenu) || !unref(getShowMenu) || (unref(getSplit) && unref(getMenuHidden)) + ? 0 + : unref(getIsMixSidebar) + ? (unref(getCollapsed) ? SIDE_BAR_MINI_WIDTH : SIDE_BAR_SHOW_TIT_MINI_WIDTH) + + (unref(getMixSideFixed) && unref(mixSideHasChildren) ? unref(getRealWidth) : 0) + : unref(getRealWidth); + + return `calc(100% - ${unref(width)}px)`; + }); + + // Set menu configuration + function setMenuSetting(menuSetting: Partial): void { + appStore.setMenuSetting(menuSetting); + } + + function toggleCollapsed() { + setMenuSetting({ + collapsed: !unref(getCollapsed), + }); + } + return { + setMenuSetting, + toggleCollapsed, + getMenuFixed, + getRealWidth, + getMenuType, + getMenuMode, + getShowMenu, + getCollapsed, + getMiniWidthNumber, + getCalcContentWidth, + getMenuWidth, + getTrigger, + getSplit, + getMenuTheme, + getCanDrag, + getCollapsedShowTitle, + getIsHorizontal, + getIsSidebarType, + getAccordion, + getShowTopMenu, + getShowHeaderTrigger, + getTopMenuAlign, + getMenuHidden, + getIsTopMenu, + getMenuBgColor, + getShowSidebar, + getIsMixMode, + getIsMixSidebar, + getCloseMixSidebarOnChange, + getMixSideTrigger, + getMixSideFixed, + mixSideHasChildren, + }; +} diff --git a/src/hooks/setting/useMultipleTabSetting.ts b/src/hooks/setting/useMultipleTabSetting.ts new file mode 100644 index 0000000..c63e013 --- /dev/null +++ b/src/hooks/setting/useMultipleTabSetting.ts @@ -0,0 +1,31 @@ +import type { MultiTabsSetting } from '#/config'; + +import { computed } from 'vue'; + +import { useAppStore } from '@/store/modules/app'; + +export function useMultipleTabSetting() { + const appStore = useAppStore(); + + const getShowMultipleTab = computed(() => appStore.getMultiTabsSetting.show); + + const getShowQuick = computed(() => appStore.getMultiTabsSetting.showQuick); + + const getShowRedo = computed(() => appStore.getMultiTabsSetting.showRedo); + + const getShowFold = computed(() => appStore.getMultiTabsSetting.showFold); + + const getAutoCollapse = computed(() => appStore.getMultiTabsSetting.autoCollapse); + + function setMultipleTabSetting(multiTabsSetting: Partial) { + appStore.setProjectConfig({ multiTabsSetting }); + } + return { + setMultipleTabSetting, + getShowMultipleTab, + getShowQuick, + getShowRedo, + getShowFold, + getAutoCollapse, + }; +} diff --git a/src/hooks/setting/useRootSetting.ts b/src/hooks/setting/useRootSetting.ts new file mode 100644 index 0000000..b5bf836 --- /dev/null +++ b/src/hooks/setting/useRootSetting.ts @@ -0,0 +1,95 @@ +import type { ProjectConfig } from '#/config'; + +import { computed } from 'vue'; + +import { useAppStore } from '@/store/modules/app'; +import { ContentEnum, ThemeEnum } from '@/enums/appEnum'; + +type RootSetting = Omit< + ProjectConfig, + 'locale' | 'headerSetting' | 'menuSetting' | 'multiTabsSetting' +>; + +export function useRootSetting() { + const appStore = useAppStore(); + + const getPageLoading = computed(() => appStore.getPageLoading); + + const getOpenKeepAlive = computed(() => appStore.getProjectConfig.openKeepAlive); + + const getSettingButtonPosition = computed(() => appStore.getProjectConfig.settingButtonPosition); + + const getCanEmbedIFramePage = computed(() => appStore.getProjectConfig.canEmbedIFramePage); + + const getPermissionMode = computed(() => appStore.getProjectConfig.permissionMode); + + const getShowLogo = computed(() => appStore.getProjectConfig.showLogo); + + const getContentMode = computed(() => appStore.getProjectConfig.contentMode); + + const getUseOpenBackTop = computed(() => appStore.getProjectConfig.useOpenBackTop); + + const getShowSettingButton = computed(() => appStore.getProjectConfig.showSettingButton); + + const getUseErrorHandle = computed(() => appStore.getProjectConfig.useErrorHandle); + + const getShowFooter = computed(() => appStore.getProjectConfig.showFooter); + + const getShowBreadCrumb = computed(() => appStore.getProjectConfig.showBreadCrumb); + + const getThemeColor = computed(() => appStore.getProjectConfig.themeColor); + + const getShowBreadCrumbIcon = computed(() => appStore.getProjectConfig.showBreadCrumbIcon); + + const getFullContent = computed(() => appStore.getProjectConfig.fullContent); + + const getColorWeak = computed(() => appStore.getProjectConfig.colorWeak); + + const getGrayMode = computed(() => appStore.getProjectConfig.grayMode); + + const getLockTime = computed(() => appStore.getProjectConfig.lockTime); + + const getShowDarkModeToggle = computed(() => appStore.getProjectConfig.showDarkModeToggle); + + const getDarkMode = computed(() => appStore.getDarkMode); + + const getLayoutContentMode = computed(() => + appStore.getProjectConfig.contentMode === ContentEnum.FULL + ? ContentEnum.FULL + : ContentEnum.FIXED, + ); + + function setRootSetting(setting: Partial) { + appStore.setProjectConfig(setting); + } + + function setDarkMode(mode: ThemeEnum) { + appStore.setDarkMode(mode); + } + return { + setRootSetting, + + getSettingButtonPosition, + getFullContent, + getColorWeak, + getGrayMode, + getLayoutContentMode, + getPageLoading, + getOpenKeepAlive, + getCanEmbedIFramePage, + getPermissionMode, + getShowLogo, + getUseErrorHandle, + getShowBreadCrumb, + getShowBreadCrumbIcon, + getUseOpenBackTop, + getShowSettingButton, + getShowFooter, + getContentMode, + getLockTime, + getThemeColor, + getDarkMode, + setDarkMode, + getShowDarkModeToggle, + }; +} diff --git a/src/hooks/setting/useTransitionSetting.ts b/src/hooks/setting/useTransitionSetting.ts new file mode 100644 index 0000000..61b3695 --- /dev/null +++ b/src/hooks/setting/useTransitionSetting.ts @@ -0,0 +1,31 @@ +import type { TransitionSetting } from '#/config'; + +import { computed } from 'vue'; + +import { useAppStore } from '@/store/modules/app'; + +export function useTransitionSetting() { + const appStore = useAppStore(); + + const getEnableTransition = computed(() => appStore.getTransitionSetting?.enable); + + const getOpenNProgress = computed(() => appStore.getTransitionSetting?.openNProgress); + + const getOpenPageLoading = computed((): boolean => { + return !!appStore.getTransitionSetting?.openPageLoading; + }); + + const getBasicTransition = computed(() => appStore.getTransitionSetting?.basicTransition); + + function setTransitionSetting(transitionSetting: Partial) { + appStore.setProjectConfig({ transitionSetting }); + } + return { + setTransitionSetting, + + getEnableTransition, + getOpenNProgress, + getOpenPageLoading, + getBasicTransition, + }; +} diff --git a/src/hooks/web/useAppInject.ts b/src/hooks/web/useAppInject.ts new file mode 100644 index 0000000..cc3cc1f --- /dev/null +++ b/src/hooks/web/useAppInject.ts @@ -0,0 +1,10 @@ +import { useAppProviderContext } from '@/components/Application'; +import { computed, unref } from 'vue'; + +export function useAppInject() { + const values = useAppProviderContext(); + + return { + getIsMobile: computed(() => unref(values.isMobile)), + }; +} diff --git a/src/hooks/web/useContentHeight.ts b/src/hooks/web/useContentHeight.ts new file mode 100644 index 0000000..af7ff1b --- /dev/null +++ b/src/hooks/web/useContentHeight.ts @@ -0,0 +1,189 @@ +import { ComputedRef, isRef, nextTick, Ref, ref, unref, watch } from 'vue'; +import { onMountedOrActivated, useWindowSizeFn } from '@vben/hooks'; +import { useLayoutHeight } from '@/layouts/default/content/useContentViewHeight'; +import { getViewportOffset } from '@/utils/domUtils'; +import { isNumber, isString } from '@/utils/is'; + +export interface CompensationHeight { + // 使用 layout Footer 高度作为判断补偿高度的条件 + useLayoutFooter: boolean; + // refs HTMLElement + elements?: Ref[]; +} + +type Upward = number | string | null | undefined; + +/** + * 动态计算内容高度,根据锚点dom最下坐标到屏幕最下坐标,根据传入dom的高度、padding、margin等值进行动态计算 + * 最终获取合适的内容高度 + * + * @param flag 用于开启计算的响应式标识 + * @param anchorRef 锚点组件 Ref + * @param subtractHeightRefs 待减去高度的组件列表 Ref + * @param substractSpaceRefs 待减去空闲空间(margins/paddings)的组件列表 Ref + * @param offsetHeightRef 计算偏移的响应式高度,计算高度时将直接减去此值 + * @param upwardSpace 向上递归减去空闲空间的 层级 或 直到指定class为止 数值为2代表向上递归两次|数值为ant-layout表示向上递归直到碰见.ant-layout为止 + * @returns 响应式高度 + */ +export function useContentHeight( + flag: ComputedRef, + anchorRef: Ref, + subtractHeightRefs: Ref[], + substractSpaceRefs: Ref[], + upwardSpace: Ref | ComputedRef | Upward = 0, + offsetHeightRef: Ref = ref(0), +) { + const contentHeight: Ref> = ref(null); + const { footerHeightRef: layoutFooterHeightRef } = useLayoutHeight(); + let compensationHeight: CompensationHeight = { + useLayoutFooter: true, + }; + + const setCompensation = (params: CompensationHeight) => { + compensationHeight = params; + }; + + function redoHeight() { + nextTick(() => { + calcContentHeight(); + }); + } + + function calcSubtractSpace( + element: Element | null | undefined, + direction: 'all' | 'top' | 'bottom' = 'all', + ): number { + function numberPx(px: string) { + return Number(px.replace(/[^\d]/g, '')); + } + let subtractHeight = 0; + const ZERO_PX = '0px'; + if (element) { + const cssStyle = getComputedStyle(element); + const marginTop = numberPx(cssStyle?.marginTop ?? ZERO_PX); + const marginBottom = numberPx(cssStyle?.marginBottom ?? ZERO_PX); + const paddingTop = numberPx(cssStyle?.paddingTop ?? ZERO_PX); + const paddingBottom = numberPx(cssStyle?.paddingBottom ?? ZERO_PX); + if (direction === 'all') { + subtractHeight += marginTop; + subtractHeight += marginBottom; + subtractHeight += paddingTop; + subtractHeight += paddingBottom; + } else if (direction === 'top') { + subtractHeight += marginTop; + subtractHeight += paddingTop; + } else { + subtractHeight += marginBottom; + subtractHeight += paddingBottom; + } + } + return subtractHeight; + } + + function getEl(element: any): Nullable { + if (element == null) { + return null; + } + return (element instanceof HTMLDivElement ? element : element.$el) as HTMLDivElement; + } + + async function calcContentHeight() { + if (!flag.value) { + return; + } + // Add a delay to get the correct height + await nextTick(); + + const anchorEl = getEl(unref(anchorRef)); + if (!anchorEl) { + return; + } + const { bottomIncludeBody } = getViewportOffset(anchorEl); + + // substract elements height + let substractHeight = 0; + subtractHeightRefs.forEach((item) => { + substractHeight += getEl(unref(item))?.offsetHeight ?? 0; + }); + + // subtract margins / paddings + let substractSpaceHeight = calcSubtractSpace(anchorEl) ?? 0; + substractSpaceRefs.forEach((item) => { + substractSpaceHeight += calcSubtractSpace(getEl(unref(item))); + }); + + // upwardSpace + let upwardSpaceHeight = 0; + function upward(element: Element | null, upwardLvlOrClass: number | string | null | undefined) { + if (element && upwardLvlOrClass) { + const parent = element.parentElement; + if (parent) { + if (isString(upwardLvlOrClass)) { + if (!parent.classList.contains(upwardLvlOrClass)) { + upwardSpaceHeight += calcSubtractSpace(parent, 'bottom'); + upward(parent, upwardLvlOrClass); + } else { + upwardSpaceHeight += calcSubtractSpace(parent, 'bottom'); + } + } else if (isNumber(upwardLvlOrClass)) { + if (upwardLvlOrClass > 0) { + upwardSpaceHeight += calcSubtractSpace(parent, 'bottom'); + upward(parent, --upwardLvlOrClass); + } + } + } + } + } + if (isRef(upwardSpace)) { + upward(anchorEl, unref(upwardSpace)); + } else { + upward(anchorEl, upwardSpace); + } + + let height = + bottomIncludeBody - + unref(layoutFooterHeightRef) - + unref(offsetHeightRef) - + substractHeight - + substractSpaceHeight - + upwardSpaceHeight; + + // compensation height + const calcCompensationHeight = () => { + compensationHeight.elements?.forEach((item) => { + height += getEl(unref(item))?.offsetHeight ?? 0; + }); + }; + if (compensationHeight.useLayoutFooter && unref(layoutFooterHeightRef) > 0) { + calcCompensationHeight(); + } else { + calcCompensationHeight(); + } + + contentHeight.value = height; + } + + onMountedOrActivated(() => { + nextTick(() => { + calcContentHeight(); + }); + }); + useWindowSizeFn( + () => { + calcContentHeight(); + }, + { wait: 50, immediate: true }, + ); + watch( + () => [layoutFooterHeightRef.value], + () => { + calcContentHeight(); + }, + { + flush: 'post', + immediate: true, + }, + ); + + return { redoHeight, setCompensation, contentHeight }; +} diff --git a/src/hooks/web/useContextMenu.ts b/src/hooks/web/useContextMenu.ts new file mode 100644 index 0000000..72ab696 --- /dev/null +++ b/src/hooks/web/useContextMenu.ts @@ -0,0 +1,13 @@ +import { onUnmounted, getCurrentInstance } from 'vue'; +import { createContextMenu, destroyContextMenu } from '@/components/ContextMenu'; +import type { ContextMenuItem } from '@/components/ContextMenu'; + +export type { ContextMenuItem }; +export function useContextMenu(authRemove = true) { + if (getCurrentInstance() && authRemove) { + onUnmounted(() => { + destroyContextMenu(); + }); + } + return [createContextMenu, destroyContextMenu]; +} diff --git a/src/hooks/web/useDesign.ts b/src/hooks/web/useDesign.ts new file mode 100644 index 0000000..9f1e5b1 --- /dev/null +++ b/src/hooks/web/useDesign.ts @@ -0,0 +1,22 @@ +import { useAppProviderContext } from '@/components/Application'; +// import { computed } from 'vue'; +// import { lowerFirst } from 'lodash-es'; +export function useDesign(scope: string) { + const values = useAppProviderContext(); + // const $style = cssModule ? useCssModule() : {}; + + // const style: Record = {}; + // if (cssModule) { + // Object.keys($style).forEach((key) => { + // // const moduleCls = $style[key]; + // const k = key.replace(new RegExp(`^${values.prefixCls}-?`, 'ig'), ''); + // style[lowerFirst(k)] = $style[key]; + // }); + // } + return { + // prefixCls: computed(() => `${values.prefixCls}-${scope}`), + prefixCls: `${values.prefixCls}-${scope}`, + prefixVar: values.prefixCls, + // style, + }; +} diff --git a/src/hooks/web/useECharts.ts b/src/hooks/web/useECharts.ts new file mode 100644 index 0000000..c5478d7 --- /dev/null +++ b/src/hooks/web/useECharts.ts @@ -0,0 +1,131 @@ +import type { EChartsOption } from 'echarts'; +import type { Ref } from 'vue'; +import { useTimeoutFn } from '@vben/hooks'; +import { tryOnUnmounted, useDebounceFn } from '@vueuse/core'; +import { unref, nextTick, watch, computed, ref } from 'vue'; +import { useEventListener } from '@/hooks/event/useEventListener'; +import { useBreakpoint } from '@/hooks/event/useBreakpoint'; +import echarts from '@/utils/lib/echarts'; +import { useRootSetting } from '@/hooks/setting/useRootSetting'; +import { useMenuSetting } from '@/hooks/setting/useMenuSetting'; + +export function useECharts( + elRef: Ref, + theme: 'light' | 'dark' | 'default' = 'default', +) { + const { getDarkMode: getSysDarkMode } = useRootSetting(); + const { getCollapsed } = useMenuSetting(); + + const getDarkMode = computed(() => { + return theme === 'default' ? getSysDarkMode.value : theme; + }); + let chartInstance: echarts.ECharts | null = null; + let resizeFn: Fn = resize; + const cacheOptions = ref({}) as Ref; + let removeResizeFn: Fn = () => {}; + + resizeFn = useDebounceFn(resize, 200); + + const getOptions = computed(() => { + if (getDarkMode.value !== 'dark') { + return cacheOptions.value as EChartsOption; + } + return { + backgroundColor: 'transparent', + ...cacheOptions.value, + } as EChartsOption; + }); + + function initCharts(t = theme) { + const el = unref(elRef); + if (!el || !unref(el)) { + return; + } + + chartInstance = echarts.init(el, t); + const { removeEvent } = useEventListener({ + el: window, + name: 'resize', + listener: resizeFn, + }); + removeResizeFn = removeEvent; + const { widthRef, screenEnum } = useBreakpoint(); + if (unref(widthRef) <= screenEnum.MD || el.offsetHeight === 0) { + useTimeoutFn(() => { + resizeFn(); + }, 30); + } + } + + function setOptions(options: EChartsOption, clear = true) { + cacheOptions.value = options; + return new Promise((resolve) => { + if (unref(elRef)?.offsetHeight === 0) { + useTimeoutFn(() => { + setOptions(unref(getOptions)); + resolve(null); + }, 30); + } + nextTick(() => { + useTimeoutFn(() => { + if (!chartInstance) { + initCharts(getDarkMode.value as 'default'); + + if (!chartInstance) return; + } + clear && chartInstance?.clear(); + + chartInstance?.setOption(unref(getOptions)); + resolve(null); + }, 30); + }); + }); + } + + function resize() { + chartInstance?.resize({ + animation: { + duration: 300, + easing: 'quadraticIn', + }, + }); + } + + watch( + () => getDarkMode.value, + (theme) => { + if (chartInstance) { + chartInstance.dispose(); + initCharts(theme as 'default'); + setOptions(cacheOptions.value); + } + }, + ); + + watch(getCollapsed, (_) => { + useTimeoutFn(() => { + resizeFn(); + }, 300); + }); + + tryOnUnmounted(() => { + if (!chartInstance) return; + removeResizeFn(); + chartInstance.dispose(); + chartInstance = null; + }); + + function getInstance(): echarts.ECharts | null { + if (!chartInstance) { + initCharts(getDarkMode.value as 'default'); + } + return chartInstance; + } + + return { + setOptions, + resize, + echarts, + getInstance, + }; +} diff --git a/src/hooks/web/useFullContent.ts b/src/hooks/web/useFullContent.ts new file mode 100644 index 0000000..05285e7 --- /dev/null +++ b/src/hooks/web/useFullContent.ts @@ -0,0 +1,28 @@ +import { computed, unref } from 'vue'; + +import { useAppStore } from '@/store/modules/app'; + +import { useRouter } from 'vue-router'; + +/** + * @description: Full screen display content + */ +export const useFullContent = () => { + const appStore = useAppStore(); + const router = useRouter(); + const { currentRoute } = router; + + // Whether to display the content in full screen without displaying the menu + const getFullContent = computed(() => { + // Query parameters, the full screen is displayed when the address bar has a full parameter + const route = unref(currentRoute); + const query = route.query; + if (query && Reflect.has(query, '__full__')) { + return true; + } + // Return to the configuration in the configuration file + return appStore.getProjectConfig.fullContent; + }); + + return { getFullContent }; +}; diff --git a/src/hooks/web/useI18n.ts b/src/hooks/web/useI18n.ts new file mode 100644 index 0000000..3c553c9 --- /dev/null +++ b/src/hooks/web/useI18n.ts @@ -0,0 +1,59 @@ +import { i18n } from '@/locales/setupI18n'; + +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]; + +function getKey(namespace: string | undefined, key: string) { + if (!namespace) { + return key; + } + if (key.startsWith(namespace)) { + return key; + } + return `${namespace}.${key}`; +} + +export function 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 (arg0: string, ...arg: I18nTranslationRestParameters) => string)( + getKey(namespace, key), + ...(arg as I18nTranslationRestParameters), + ); + }; + return { + ...methods, + t: tFn, + }; +} + +// Why write this function? +// Mainly to configure the vscode i18nn ally plugin. This function is only used for routing and menus. Please use useI18n for other places + +// 为什么要编写此函数? +// 主要用于配合vscode i18nn ally插件。此功能仅用于路由和菜单。请在其他地方使用useI18n +export const t = (key: string) => key; diff --git a/src/hooks/web/useLockPage.ts b/src/hooks/web/useLockPage.ts new file mode 100644 index 0000000..90ce336 --- /dev/null +++ b/src/hooks/web/useLockPage.ts @@ -0,0 +1,75 @@ +import { computed, onUnmounted, unref, watchEffect } from 'vue'; +import { useThrottleFn } from '@vueuse/core'; + +import { useAppStore } from '@/store/modules/app'; +import { useLockStore } from '@/store/modules/lock'; + +import { useUserStore } from '@/store/modules/user'; +import { useRootSetting } from '../setting/useRootSetting'; + +export function useLockPage() { + const { getLockTime } = useRootSetting(); + const lockStore = useLockStore(); + const userStore = useUserStore(); + const appStore = useAppStore(); + + let timeId: TimeoutHandle; + + function clear(): void { + window.clearTimeout(timeId); + } + + function resetCalcLockTimeout(): void { + // not login + if (!userStore.getToken) { + clear(); + return; + } + const lockTime = appStore.getProjectConfig.lockTime; + if (!lockTime || lockTime < 1) { + clear(); + return; + } + clear(); + + timeId = setTimeout( + () => { + lockPage(); + }, + lockTime * 60 * 1000, + ); + } + + function lockPage(): void { + lockStore.setLockInfo({ + isLock: true, + pwd: undefined, + }); + } + + watchEffect((onClean) => { + if (userStore.getToken) { + resetCalcLockTimeout(); + } else { + clear(); + } + onClean(() => { + clear(); + }); + }); + + onUnmounted(() => { + clear(); + }); + + const keyupFn = useThrottleFn(resetCalcLockTimeout, 2000); + + return computed(() => { + if (unref(getLockTime)) { + return { onKeyup: keyupFn, onMousemove: keyupFn }; + } else { + clear(); + return {}; + } + }); +} diff --git a/src/hooks/web/useMessage.tsx b/src/hooks/web/useMessage.tsx new file mode 100644 index 0000000..9806c91 --- /dev/null +++ b/src/hooks/web/useMessage.tsx @@ -0,0 +1,113 @@ +import type { ModalFuncProps } from 'ant-design-vue/lib/modal/Modal'; +import { Modal, message as Message, notification } from 'ant-design-vue'; +import { InfoCircleFilled, CheckCircleFilled, CloseCircleFilled } from '@ant-design/icons-vue'; +import { NotificationArgsProps, ConfigProps } from 'ant-design-vue/lib/notification'; +import { useI18n } from './useI18n'; +import { isString } from '@/utils/is'; + +export interface NotifyApi { + info(config: NotificationArgsProps): void; + success(config: NotificationArgsProps): void; + error(config: NotificationArgsProps): void; + warn(config: NotificationArgsProps): void; + warning(config: NotificationArgsProps): void; + open(args: NotificationArgsProps): void; + close(key: String): void; + config(options: ConfigProps): void; + destroy(): void; +} + +export declare type NotificationPlacement = 'topLeft' | 'topRight' | 'bottomLeft' | 'bottomRight'; +export declare type IconType = 'success' | 'info' | 'error' | 'warning'; +export interface ModalOptionsEx extends Omit { + iconType: 'warning' | 'success' | 'error' | 'info'; +} +export type ModalOptionsPartial = Partial & Pick; + +function getIcon(iconType: string) { + if (iconType === 'warning') { + return ; + } else if (iconType === 'success') { + return ; + } else if (iconType === 'info') { + return ; + } else { + return ; + } +} + +function renderContent({ content }: Pick) { + if (isString(content)) { + return
${content as string}
`}>; + } else { + return content; + } +} + +/** + * @description: Create confirmation box + */ +function createConfirm(options: ModalOptionsEx) { + const iconType = options.iconType || 'warning'; + Reflect.deleteProperty(options, 'iconType'); + const opt: ModalFuncProps = { + centered: true, + icon: getIcon(iconType), + ...options, + content: renderContent(options), + }; + return Modal.confirm(opt); +} + +const getBaseOptions = () => { + const { t } = useI18n(); + return { + okText: t('common.okText'), + centered: true, + }; +}; + +function createModalOptions(options: ModalOptionsPartial, icon: string): ModalOptionsPartial { + return { + ...getBaseOptions(), + ...options, + content: renderContent(options), + icon: getIcon(icon), + }; +} + +function createSuccessModal(options: ModalOptionsPartial) { + return Modal.success(createModalOptions(options, 'success')); +} + +function createErrorModal(options: ModalOptionsPartial) { + return Modal.error(createModalOptions(options, 'error')); +} + +function createInfoModal(options: ModalOptionsPartial) { + return Modal.info(createModalOptions(options, 'info')); +} + +function createWarningModal(options: ModalOptionsPartial) { + return Modal.warning(createModalOptions(options, 'warning')); +} + +notification.config({ + placement: 'topRight', + duration: 3, +}); + +/** + * @description: message + */ +export function useMessage() { + return { + createMessage: Message, + notification: notification as NotifyApi, + createConfirm, + createSuccessModal, + createErrorModal, + createInfoModal, + createWarningModal, + }; +} diff --git a/src/hooks/web/usePage.ts b/src/hooks/web/usePage.ts new file mode 100644 index 0000000..0d60d45 --- /dev/null +++ b/src/hooks/web/usePage.ts @@ -0,0 +1,106 @@ +import type { RouteLocationRaw, Router } from 'vue-router'; + +import { PageEnum } from '@/enums/pageEnum'; +import { unref } from 'vue'; + +import { useRouter } from 'vue-router'; +import { REDIRECT_NAME } from '@/router/constant'; +import { isHttpUrl } from '@/utils/is'; +import { openWindow } from '@/utils'; + +import { useMultipleTabStore } from '@/store/modules/multipleTab'; + +export type PathAsPageEnum = T extends { path: string } ? T & { path: PageEnum } : T; +export type RouteLocationRawEx = PathAsPageEnum; + +function handleError(e: Error) { + console.error(e); +} + +export enum GoType { + 'replace', + 'after', +} + +/** + * page switch + */ +export function useGo(_router?: Router) { + const { push, replace, currentRoute } = _router || useRouter(); + + function go(opt?: RouteLocationRawEx): void; + function go(opt: RouteLocationRawEx, isReplace: boolean): void; + function go(opt: RouteLocationRawEx, goType: GoType): void; + function go( + opt: RouteLocationRawEx = PageEnum.BASE_HOME, + goTypeOrIsReplace: boolean | GoType = false, + ) { + if (!opt) { + return; + } + let path = unref(opt) as string; + if (path[0] === '/') { + path = path.slice(1); + } + if (isHttpUrl(path)) { + return openWindow(path); + } + + const isReplace = goTypeOrIsReplace === true || goTypeOrIsReplace === GoType.replace; + const isAfter = goTypeOrIsReplace === GoType.after; + + if (isReplace) { + replace(opt).catch(handleError); + } else if (isAfter) { + const tabStore = useMultipleTabStore(); + const currentName = unref(currentRoute).name; + // 当前 tab + const currentIndex = tabStore.getTabList.findIndex((item) => item.name === currentName); + // 当前 tab 数量 + const currentCount = tabStore.getTabList.length; + push(opt) + .then(() => { + if (tabStore.getTabList.length > currentCount) { + // 产生新 tab + // 新 tab(也是最后一个) + const targetIndex = tabStore.getTabList.length - 1; + // 新 tab 在 当前 tab 的后面 + if (currentIndex > -1 && targetIndex > currentIndex) { + // 移动 tab + tabStore.sortTabs(targetIndex, currentIndex + 1); + } + } + }) + .catch(handleError); + } else { + push(opt).catch(handleError); + } + } + return go; +} + +/** + * @description: redo current page + */ +export const useRedo = (_router?: Router) => { + const { replace, currentRoute } = _router || useRouter(); + const { query, params = {}, name, fullPath } = unref(currentRoute.value); + function redo(): Promise { + return new Promise((resolve) => { + if (name === REDIRECT_NAME) { + resolve(false); + return; + } + if (name && Object.keys(params).length > 0) { + params['_origin_params'] = JSON.stringify(params ?? {}); + params['_redirect_type'] = 'name'; + params['path'] = String(name); + } else { + params['_redirect_type'] = 'path'; + params['path'] = fullPath; + } + replace({ name: REDIRECT_NAME, params, query }).then(() => resolve(true)); + }); + } + return redo; +}; diff --git a/src/hooks/web/usePagination.ts b/src/hooks/web/usePagination.ts new file mode 100644 index 0000000..1e19913 --- /dev/null +++ b/src/hooks/web/usePagination.ts @@ -0,0 +1,34 @@ +import type { Ref } from 'vue'; +import { ref, unref, computed } from 'vue'; + +function pagination(list: T[], pageNo: number, pageSize: number): T[] { + const offset = (pageNo - 1) * Number(pageSize); + const ret = + offset + Number(pageSize) >= list.length + ? list.slice(offset, list.length) + : list.slice(offset, offset + Number(pageSize)); + return ret; +} + +export function usePagination(list: Ref, pageSize: number) { + const currentPage = ref(1); + const pageSizeRef = ref(pageSize); + + const getPaginationList = computed(() => { + return pagination(unref(list), unref(currentPage), unref(pageSizeRef)); + }); + + const getTotal = computed(() => { + return unref(list).length; + }); + + function setCurrentPage(page: number) { + currentPage.value = page; + } + + function setPageSize(pageSize: number) { + pageSizeRef.value = pageSize; + } + + return { setCurrentPage, getTotal, setPageSize, getPaginationList }; +} diff --git a/src/hooks/web/usePermission.ts b/src/hooks/web/usePermission.ts new file mode 100644 index 0000000..2ffc61e --- /dev/null +++ b/src/hooks/web/usePermission.ts @@ -0,0 +1,119 @@ +import type { RouteRecordRaw } from 'vue-router'; + +import { useAppStore } from '@/store/modules/app'; +import { usePermissionStore } from '@/store/modules/permission'; +import { useUserStore } from '@/store/modules/user'; + +import { useTabs } from './useTabs'; + +import { router, resetRouter } from '@/router'; +// import { RootRoute } from '@/router/routes'; + +import projectSetting from '@/settings/projectSetting'; +import { PermissionModeEnum } from '@/enums/appEnum'; +import { RoleEnum } from '@/enums/roleEnum'; + +import { intersection } from 'lodash-es'; +import { isArray } from '@/utils/is'; +import { useMultipleTabStore } from '@/store/modules/multipleTab'; + +// User permissions related operations +export function usePermission() { + const userStore = useUserStore(); + const appStore = useAppStore(); + const permissionStore = usePermissionStore(); + const { closeAll } = useTabs(router); + + /** + * Change permission mode + */ + async function togglePermissionMode() { + appStore.setProjectConfig({ + permissionMode: + appStore.projectConfig?.permissionMode === PermissionModeEnum.BACK + ? PermissionModeEnum.ROUTE_MAPPING + : PermissionModeEnum.BACK, + }); + location.reload(); + } + + /** + * Reset and regain authority resource information + * 重置和重新获得权限资源信息 + * @param id + */ + async function resume() { + const tabStore = useMultipleTabStore(); + tabStore.clearCacheTabs(); + resetRouter(); + const routes = await permissionStore.buildRoutesAction(); + routes.forEach((route) => { + router.addRoute(route as unknown as RouteRecordRaw); + }); + permissionStore.setLastBuildMenuTime(); + closeAll(); + } + + /** + * Determine whether there is permission + */ + function hasPermission(value?: RoleEnum | RoleEnum[] | string | string[], def = true): boolean { + // Visible by default + if (!value) { + return def; + } + + const permMode = appStore.getProjectConfig.permissionMode; + + if ([PermissionModeEnum.ROUTE_MAPPING, PermissionModeEnum.ROLE].includes(permMode)) { + if (!isArray(value)) { + return userStore.getRoleList?.includes(value as RoleEnum); + } + return (intersection(value, userStore.getRoleList) as RoleEnum[]).length > 0; + } + + if (PermissionModeEnum.BACK === permMode) { + const allCodeList = permissionStore.getPermCodeList as string[]; + if (!isArray(value)) { + const splits = ['||', '&&']; + const splitName = splits.find((item) => value.includes(item)); + if (splitName) { + const splitCodes = value.split(splitName); + return splitName === splits[0] + ? intersection(splitCodes, allCodeList).length > 0 + : intersection(splitCodes, allCodeList).length === splitCodes.length; + } + return allCodeList.includes(value); + } + return (intersection(value, allCodeList) as string[]).length > 0; + } + return true; + } + + /** + * Change roles + * @param roles + */ + async function changeRole(roles: RoleEnum | RoleEnum[]): Promise { + if (projectSetting.permissionMode !== PermissionModeEnum.ROUTE_MAPPING) { + throw new Error( + 'Please switch PermissionModeEnum to ROUTE_MAPPING mode in the configuration to operate!', + ); + } + + if (!isArray(roles)) { + roles = [roles]; + } + userStore.setRoleList(roles); + await resume(); + } + + /** + * refresh menu data + */ + async function refreshMenu() { + resume(); + } + + return { changeRole, hasPermission, togglePermissionMode, refreshMenu }; +} diff --git a/src/hooks/web/useScript.ts b/src/hooks/web/useScript.ts new file mode 100644 index 0000000..9707116 --- /dev/null +++ b/src/hooks/web/useScript.ts @@ -0,0 +1,46 @@ +import { onMounted, onUnmounted, ref } from 'vue'; + +interface ScriptOptions { + src: string; +} + +export function useScript(opts: ScriptOptions) { + const isLoading = ref(false); + const error = ref(false); + const success = ref(false); + let script: HTMLScriptElement; + + const promise = new Promise((resolve, reject) => { + onMounted(() => { + script = document.createElement('script'); + script.type = 'text/javascript'; + script.onload = function () { + isLoading.value = false; + success.value = true; + error.value = false; + resolve(''); + }; + + script.onerror = function (err) { + isLoading.value = false; + success.value = false; + error.value = true; + reject(err); + }; + + script.src = opts.src; + document.head.appendChild(script); + }); + }); + + onUnmounted(() => { + script && script.remove(); + }); + + return { + isLoading, + error, + success, + toPromise: () => promise, + }; +} diff --git a/src/hooks/web/useSortable.ts b/src/hooks/web/useSortable.ts new file mode 100644 index 0000000..ab7da70 --- /dev/null +++ b/src/hooks/web/useSortable.ts @@ -0,0 +1,23 @@ +import { nextTick, unref } from 'vue'; +import type { Ref } from 'vue'; +import type { Options } from 'sortablejs'; + +export function useSortable(el?: HTMLElement | Ref, options?: Options) { + function initSortable() { + nextTick(async () => { + el = unref(el); + + if (!el) return; + + const Sortable = (await import('sortablejs')).default; + Sortable.create(el, { + animation: 100, + delay: 400, + delayOnTouchOnly: true, + ...options, + }); + }); + } + + return { initSortable }; +} diff --git a/src/hooks/web/useTabs.ts b/src/hooks/web/useTabs.ts new file mode 100644 index 0000000..ab13e45 --- /dev/null +++ b/src/hooks/web/useTabs.ts @@ -0,0 +1,103 @@ +import type { RouteLocationNormalized, Router } from 'vue-router'; + +import { useRouter } from 'vue-router'; +import { unref } from 'vue'; + +import { useMultipleTabStore } from '@/store/modules/multipleTab'; +import { useAppStore } from '@/store/modules/app'; + +enum TableActionEnum { + REFRESH, + CLOSE_ALL, + CLOSE_LEFT, + CLOSE_RIGHT, + CLOSE_OTHER, + CLOSE_CURRENT, + CLOSE, +} + +export function useTabs(_router?: Router) { + const appStore = useAppStore(); + + function canIUseTabs(): boolean { + const { show } = appStore.getMultiTabsSetting; + if (!show) { + throw new Error('The multi-tab page is currently not open, please open it in the settings!'); + } + return !!show; + } + + const tabStore = useMultipleTabStore(); + const router = _router || useRouter(); + + const { currentRoute } = router; + + function getCurrentTab() { + const route = unref(currentRoute); + return tabStore.getTabList.find((item) => item.fullPath === route.fullPath)!; + } + + async function updateTabTitle(title: string, tab?: RouteLocationNormalized) { + const canIUse = canIUseTabs; + if (!canIUse) { + return; + } + const targetTab = tab || getCurrentTab(); + await tabStore.setTabTitle(title, targetTab); + } + + async function updateTabPath(path: string, tab?: RouteLocationNormalized) { + const canIUse = canIUseTabs; + if (!canIUse) { + return; + } + const targetTab = tab || getCurrentTab(); + await tabStore.updateTabPath(path, targetTab); + } + + async function handleTabAction(action: TableActionEnum, tab?: RouteLocationNormalized) { + const canIUse = canIUseTabs; + if (!canIUse) { + return; + } + const currentTab = getCurrentTab(); + switch (action) { + case TableActionEnum.REFRESH: + await tabStore.refreshPage(router); + break; + + case TableActionEnum.CLOSE_ALL: + await tabStore.closeAllTab(router); + break; + + case TableActionEnum.CLOSE_LEFT: + await tabStore.closeLeftTabs(currentTab, router); + break; + + case TableActionEnum.CLOSE_RIGHT: + await tabStore.closeRightTabs(currentTab, router); + break; + + case TableActionEnum.CLOSE_OTHER: + await tabStore.closeOtherTabs(currentTab, router); + break; + + case TableActionEnum.CLOSE_CURRENT: + case TableActionEnum.CLOSE: + await tabStore.closeTab(tab || currentTab, router); + break; + } + } + + return { + refreshPage: () => handleTabAction(TableActionEnum.REFRESH), + closeAll: () => handleTabAction(TableActionEnum.CLOSE_ALL), + closeLeft: () => handleTabAction(TableActionEnum.CLOSE_LEFT), + closeRight: () => handleTabAction(TableActionEnum.CLOSE_RIGHT), + closeOther: () => handleTabAction(TableActionEnum.CLOSE_OTHER), + closeCurrent: () => handleTabAction(TableActionEnum.CLOSE_CURRENT), + close: (tab?: RouteLocationNormalized) => handleTabAction(TableActionEnum.CLOSE, tab), + setTitle: (title: string, tab?: RouteLocationNormalized) => updateTabTitle(title, tab), + updatePath: (fullPath: string, tab?: RouteLocationNormalized) => updateTabPath(fullPath, tab), + }; +} diff --git a/src/hooks/web/useTitle.ts b/src/hooks/web/useTitle.ts new file mode 100644 index 0000000..e3a7653 --- /dev/null +++ b/src/hooks/web/useTitle.ts @@ -0,0 +1,34 @@ +import { watch, unref } from 'vue'; +import { useI18n } from '@/hooks/web/useI18n'; +import { useTitle as usePageTitle } from '@vueuse/core'; +import { useGlobSetting } from '@/hooks/setting'; +import { useRouter } from 'vue-router'; +import { useLocaleStore } from '@/store/modules/locale'; +import { REDIRECT_NAME } from '@/router/constant'; + +/** + * Listening to page changes and dynamically changing site titles + */ +export function useTitle() { + const { title } = useGlobSetting(); + const { t } = useI18n(); + const { currentRoute } = useRouter(); + const localeStore = useLocaleStore(); + + const pageTitle = usePageTitle(); + + watch( + [() => currentRoute.value.path, () => localeStore.getLocale], + () => { + const route = unref(currentRoute); + + if (route.name === REDIRECT_NAME) { + return; + } + + const tTitle = t(route?.meta?.title as string); + pageTitle.value = tTitle ? ` ${tTitle} - ${title} ` : `${title}`; + }, + { immediate: true }, + ); +} diff --git a/src/hooks/web/useWatermark.ts b/src/hooks/web/useWatermark.ts new file mode 100644 index 0000000..eb38f60 --- /dev/null +++ b/src/hooks/web/useWatermark.ts @@ -0,0 +1,170 @@ +import { getCurrentInstance, onBeforeUnmount, ref, Ref, shallowRef, unref } from 'vue'; +import { useRafThrottle } from '@/utils/domUtils'; +import { addResizeListener, removeResizeListener } from '@/utils/event'; +import { isDef } from '@/utils/is'; + +const watermarkSymbol = 'watermark-dom'; +const updateWatermarkText = ref(null); + +type UseWatermarkRes = { + setWatermark: (str: string) => void; + clear: () => void; + clearAll: () => void; + obInstance?: MutationObserver; + targetElement?: HTMLElement; + parentElement?: HTMLElement; +}; + +const sourceMap = new Map>(); + +function createBase64(str: string) { + const can = document.createElement('canvas'); + const width = 300; + const height = 240; + Object.assign(can, { width, height }); + + const cans = can.getContext('2d'); + if (cans) { + cans.rotate((-20 * Math.PI) / 180); + cans.font = '15px Vedana'; + cans.fillStyle = 'rgba(0, 0, 0, 0.15)'; + cans.textAlign = 'left'; + cans.textBaseline = 'middle'; + cans.fillText(str, width / 20, height); + // todo 自定义水印样式 + } + return can.toDataURL('image/png'); +} +const resetWatermarkStyle = (element: HTMLElement, watermarkText: string) => { + element.className = '__' + watermarkSymbol; + element.style.pointerEvents = 'none'; + element.style.top = '0px'; + element.style.left = '0px'; + element.style.position = 'absolute'; + element.style.zIndex = '100000'; + element.style.height = '100%'; + element.style.width = '100%'; + element.style.background = `url(${createBase64( + unref(updateWatermarkText) || watermarkText, + )}) left top repeat`; +}; + +const obFn = () => { + const obInstance = new MutationObserver((mutationRecords) => { + for (const mutation of mutationRecords) { + for (const node of Array.from(mutation.removedNodes)) { + const target = Array.from(sourceMap.values()).find((item) => item.targetElement === node); + if (!target) return; + const { targetElement, parentElement } = target; + // 父元素的子元素水印如果被删除 重新插入被删除的水印(防篡改,插入通过控制台删除的水印) + if (!parentElement?.contains(targetElement as Node | null)) { + target?.parentElement?.appendChild(node as HTMLElement); + } + } + if (mutation.attributeName === 'style' && mutation.target) { + const _target = mutation.target as HTMLElement; + if (_target.className === '__' + watermarkSymbol) { + resetWatermarkStyle(_target as HTMLElement, _target?.['data-watermark-text']); + } + } + } + }); + return obInstance; +}; + +export function useWatermark( + appendEl: Ref = ref(document.body) as Ref, +): UseWatermarkRes { + const domSymbol = Symbol(watermarkSymbol); + const appendElRaw = unref(appendEl); + if (appendElRaw && sourceMap.has(domSymbol)) { + const { setWatermark, clear } = sourceMap.get(domSymbol) as UseWatermarkRes; + return { setWatermark, clear, clearAll }; + } + const func = useRafThrottle(function () { + const el = unref(appendEl); + if (!el) return; + const { clientHeight: height, clientWidth: width } = el; + updateWatermark({ height, width }); + }); + const watermarkEl = shallowRef(); + const clear = () => { + const domId = unref(watermarkEl); + watermarkEl.value = undefined; + const el = unref(appendEl); + sourceMap.has(domSymbol) && sourceMap.get(domSymbol)?.obInstance?.disconnect(); + sourceMap.delete(domSymbol); + if (!el) return; + domId && el.removeChild(domId); + removeResizeListener(el, func); + }; + + function updateWatermark( + options: { + width?: number; + height?: number; + str?: string; + } = {}, + ) { + const el = unref(watermarkEl); + if (!el) return; + if (isDef(options.width)) { + el.style.width = `${options.width}px`; + } + if (isDef(options.height)) { + el.style.height = `${options.height}px`; + } + if (isDef(options.str)) { + el.style.background = `url(${createBase64(options.str)}) left top repeat`; + } + } + + const createWatermark = (str: string) => { + if (unref(watermarkEl) && sourceMap.has(domSymbol)) { + updateWatermarkText.value = str; + updateWatermark({ str }); + return; + } + const div = document.createElement('div'); + div['data-watermark-text'] = str; //自定义属性 用于恢复水印 + updateWatermarkText.value = str; + watermarkEl.value = div; + resetWatermarkStyle(div, str); + const el = unref(appendEl); + if (!el) return; + const { clientHeight: height, clientWidth: width } = el; + updateWatermark({ str, width, height }); + el.appendChild(div); + sourceMap.set(domSymbol, { + setWatermark, + clear, + parentElement: el, + targetElement: div, + obInstance: obFn(), + }); + sourceMap.get(domSymbol)?.obInstance?.observe(el, { + childList: true, // 子节点的变动(指新增,删除或者更改) + subtree: true, // 该观察器应用于该节点的所有后代节点 + attributes: true, // 属性的变动 + }); + }; + + function setWatermark(str: string) { + createWatermark(str); + addResizeListener(document.documentElement, func); + const instance = getCurrentInstance(); + if (instance) { + onBeforeUnmount(() => { + clear(); + }); + } + } + return { setWatermark, clear, clearAll }; +} + +function clearAll() { + Array.from(sourceMap.values()).forEach((item) => { + item?.obInstance?.disconnect(); + item.clear(); + }); +} diff --git a/src/layouts/default/content/index.vue b/src/layouts/default/content/index.vue new file mode 100644 index 0000000..ae5182d --- /dev/null +++ b/src/layouts/default/content/index.vue @@ -0,0 +1,47 @@ + + + diff --git a/src/layouts/default/content/useContentContext.ts b/src/layouts/default/content/useContentContext.ts new file mode 100644 index 0000000..133c4cf --- /dev/null +++ b/src/layouts/default/content/useContentContext.ts @@ -0,0 +1,17 @@ +import type { InjectionKey, ComputedRef } from 'vue'; +import { createContext, useContext } from '@/hooks/core/useContext'; + +export interface ContentContextProps { + contentHeight: ComputedRef; + setPageHeight: (height: number) => Promise; +} + +const key: InjectionKey = Symbol(); + +export function createContentContext(context: ContentContextProps) { + return createContext(context, key, { native: true }); +} + +export function useContentContext() { + return useContext(key); +} diff --git a/src/layouts/default/content/useContentViewHeight.ts b/src/layouts/default/content/useContentViewHeight.ts new file mode 100644 index 0000000..0a9ef9e --- /dev/null +++ b/src/layouts/default/content/useContentViewHeight.ts @@ -0,0 +1,41 @@ +import { ref, computed, unref } from 'vue'; +import { createPageContext } from '@/hooks/component/usePageContext'; +import { useWindowSizeFn } from '@vben/hooks'; + +const headerHeightRef = ref(0); +const footerHeightRef = ref(0); + +export function useLayoutHeight() { + function setHeaderHeight(val) { + headerHeightRef.value = val; + } + function setFooterHeight(val) { + footerHeightRef.value = val; + } + return { headerHeightRef, footerHeightRef, setHeaderHeight, setFooterHeight }; +} + +export function useContentViewHeight() { + const contentHeight = ref(window.innerHeight); + const pageHeight = ref(window.innerHeight); + const getViewHeight = computed(() => { + return unref(contentHeight) - unref(headerHeightRef) - unref(footerHeightRef) || 0; + }); + + useWindowSizeFn( + () => { + contentHeight.value = window.innerHeight; + }, + { wait: 100, immediate: true }, + ); + + async function setPageHeight(height: number) { + pageHeight.value = height; + } + + createPageContext({ + contentHeight: getViewHeight, + setPageHeight, + pageHeight, + }); +} diff --git a/src/layouts/default/feature/index.vue b/src/layouts/default/feature/index.vue new file mode 100644 index 0000000..4f1fd62 --- /dev/null +++ b/src/layouts/default/feature/index.vue @@ -0,0 +1,77 @@ + + + diff --git a/src/layouts/default/footer/index.vue b/src/layouts/default/footer/index.vue new file mode 100644 index 0000000..689f795 --- /dev/null +++ b/src/layouts/default/footer/index.vue @@ -0,0 +1,81 @@ + + + diff --git a/src/layouts/default/header/MultipleHeader.vue b/src/layouts/default/header/MultipleHeader.vue new file mode 100644 index 0000000..5fda8cb --- /dev/null +++ b/src/layouts/default/header/MultipleHeader.vue @@ -0,0 +1,122 @@ + + + diff --git a/src/layouts/default/header/components/Breadcrumb.vue b/src/layouts/default/header/components/Breadcrumb.vue new file mode 100644 index 0000000..a387d90 --- /dev/null +++ b/src/layouts/default/header/components/Breadcrumb.vue @@ -0,0 +1,204 @@ + + + diff --git a/src/layouts/default/header/components/ChangeApi/index.vue b/src/layouts/default/header/components/ChangeApi/index.vue new file mode 100644 index 0000000..107d2d9 --- /dev/null +++ b/src/layouts/default/header/components/ChangeApi/index.vue @@ -0,0 +1,81 @@ + + diff --git a/src/layouts/default/header/components/CloudQuery.vue b/src/layouts/default/header/components/CloudQuery.vue new file mode 100644 index 0000000..4f5ad57 --- /dev/null +++ b/src/layouts/default/header/components/CloudQuery.vue @@ -0,0 +1,98 @@ + + + + diff --git a/src/layouts/default/header/components/ErrorAction.vue b/src/layouts/default/header/components/ErrorAction.vue new file mode 100644 index 0000000..f865c97 --- /dev/null +++ b/src/layouts/default/header/components/ErrorAction.vue @@ -0,0 +1,36 @@ + + diff --git a/src/layouts/default/header/components/FullScreen.vue b/src/layouts/default/header/components/FullScreen.vue new file mode 100644 index 0000000..6fa5d7d --- /dev/null +++ b/src/layouts/default/header/components/FullScreen.vue @@ -0,0 +1,34 @@ + + diff --git a/src/layouts/default/header/components/bigScreen.vue b/src/layouts/default/header/components/bigScreen.vue new file mode 100644 index 0000000..086d035 --- /dev/null +++ b/src/layouts/default/header/components/bigScreen.vue @@ -0,0 +1,15 @@ + + diff --git a/src/layouts/default/header/components/index.ts b/src/layouts/default/header/components/index.ts new file mode 100644 index 0000000..b42d4f5 --- /dev/null +++ b/src/layouts/default/header/components/index.ts @@ -0,0 +1,18 @@ +import { createAsyncComponent } from '@/utils/factory/createAsyncComponent'; +import FullScreen from './FullScreen.vue'; + +export const UserDropDown = createAsyncComponent(() => import('./user-dropdown/index.vue'), { + loading: true, +}); + +export const LayoutBreadcrumb = createAsyncComponent(() => import('./Breadcrumb.vue')); + +export const Notify = createAsyncComponent(() => import('./notify/index.vue')); + +export const ErrorAction = createAsyncComponent(() => import('./ErrorAction.vue')); + +export const BigScreen = createAsyncComponent(() => import('./bigScreen.vue')); + +export const CloudQuery = createAsyncComponent(() => import('./CloudQuery.vue')); + +export { FullScreen }; diff --git a/src/layouts/default/header/components/lock/LockModal.vue b/src/layouts/default/header/components/lock/LockModal.vue new file mode 100644 index 0000000..0920f36 --- /dev/null +++ b/src/layouts/default/header/components/lock/LockModal.vue @@ -0,0 +1,115 @@ + + + diff --git a/src/layouts/default/header/components/notify/NoticeList.vue b/src/layouts/default/header/components/notify/NoticeList.vue new file mode 100644 index 0000000..51e4633 --- /dev/null +++ b/src/layouts/default/header/components/notify/NoticeList.vue @@ -0,0 +1,176 @@ + + + diff --git a/src/layouts/default/header/components/notify/data.ts b/src/layouts/default/header/components/notify/data.ts new file mode 100644 index 0000000..f436510 --- /dev/null +++ b/src/layouts/default/header/components/notify/data.ts @@ -0,0 +1,41 @@ +export interface ListItem { + id: string; + // 头像 + avatar: string; + // 通知的标题内容 + title: string; + // 是否在标题上显示删除线 + titleDelete?: boolean; + datetime: string; + type: string; + read?: boolean; + description: string; + clickClose?: boolean; + extra?: string; + color?: string; +} + +export interface TabItem { + key: string; + name: string; + list: ListItem[]; + unreadlist?: ListItem[]; +} + +export const tabListData: TabItem[] = [ + { + key: '1', + name: '消息', + list: [], + }, + { + key: '2', + name: '通知', + list: [], + }, + { + key: '3', + name: '待办', + list: [], + }, +]; diff --git a/src/layouts/default/header/components/notify/index.vue b/src/layouts/default/header/components/notify/index.vue new file mode 100644 index 0000000..166617c --- /dev/null +++ b/src/layouts/default/header/components/notify/index.vue @@ -0,0 +1,342 @@ + + + + diff --git a/src/layouts/default/header/components/user-dropdown/DropMenuItem.vue b/src/layouts/default/header/components/user-dropdown/DropMenuItem.vue new file mode 100644 index 0000000..30a77e3 --- /dev/null +++ b/src/layouts/default/header/components/user-dropdown/DropMenuItem.vue @@ -0,0 +1,26 @@ + + diff --git a/src/layouts/default/header/components/user-dropdown/index.vue b/src/layouts/default/header/components/user-dropdown/index.vue new file mode 100644 index 0000000..0f1a38f --- /dev/null +++ b/src/layouts/default/header/components/user-dropdown/index.vue @@ -0,0 +1,186 @@ + + + diff --git a/src/layouts/default/header/index.less b/src/layouts/default/header/index.less new file mode 100644 index 0000000..ab734f1 --- /dev/null +++ b/src/layouts/default/header/index.less @@ -0,0 +1,196 @@ +@header-trigger-prefix-cls: ~'@{namespace}-layout-header-trigger'; +@header-prefix-cls: ~'@{namespace}-layout-header'; +@breadcrumb-prefix-cls: ~'@{namespace}-layout-breadcrumb'; +@logo-prefix-cls: ~'@{namespace}-app-logo'; + +.ant-layout .@{header-prefix-cls} { + display: flex; + align-items: center; + justify-content: space-between; + height: @header-height; + margin-left: -1px; + padding: 0; + background-color: @white; + color: @white; + line-height: @header-height; + + &--mobile { + .@{breadcrumb-prefix-cls}, + .error-action, + .notify-item, + .fullscreen-item { + display: none; + } + + .@{logo-prefix-cls} { + min-width: unset; + padding-right: 0; + + &__title { + display: none; + } + } + .@{header-trigger-prefix-cls} { + padding: 0 4px 0 8px !important; + } + .@{header-prefix-cls}-action { + padding-right: 4px; + } + } + + &--fixed { + position: fixed; + z-index: @layout-header-fixed-z-index; + top: 0; + left: 0; + width: 100%; + } + + &-logo { + min-width: 192px; + height: @header-height; + padding: 0 10px; + font-size: 14px; + + img { + width: @logo-width; + height: @logo-width; + margin-right: 2px; + } + } + + &-left { + display: flex; + align-items: center; + height: 100%; + + .@{header-trigger-prefix-cls} { + display: flex; + align-items: center; + height: 100%; + padding: 1px 10px 0; + cursor: pointer; + + .anticon { + font-size: 16px; + } + + &.light { + &:hover { + background-color: @header-light-bg-hover-color; + } + + svg { + fill: #000; + } + } + + &.dark { + &:hover { + background-color: @header-dark-bg-hover-color; + } + } + } + } + + &-menu { + flex: 1; + align-items: center; + min-width: 0; + height: 100%; + } + + &-action { + display: flex; + // padding-right: 12px; + align-items: center; + min-width: 180px; + + &__item { + display: flex !important; + align-items: center; + height: @header-height; + padding: 0 2px; + font-size: 1.2em; + cursor: pointer; + + .ant-badge { + height: @header-height; + line-height: @header-height; + } + + .ant-badge-dot { + top: 14px; + right: 2px; + } + } + + span[role='img'] { + padding: 0 8px; + } + } + + &--light { + border-bottom: 1px solid @header-light-bottom-border-color; + border-left: 1px solid @header-light-bottom-border-color; + background-color: @white !important; + + .@{header-prefix-cls}-logo { + color: @text-color-base; + + &:hover { + background-color: @header-light-bg-hover-color; + } + } + + .@{header-prefix-cls}-action { + &__item { + color: @text-color-base; + + .app-iconify { + padding: 0 10px; + font-size: 16px !important; + } + + &:hover { + background-color: @header-light-bg-hover-color; + } + } + + &-icon, + span[role='img'] { + color: @text-color-base; + } + } + } + + &--dark { + border-bottom: 1px solid @border-color-base; + border-left: 1px solid @border-color-base; + background-color: @header-dark-bg-color !important; + .@{header-prefix-cls}-logo { + &:hover { + background-color: @header-dark-bg-hover-color; + } + } + + .@{header-prefix-cls}-action { + &__item { + .app-iconify { + padding: 0 10px; + font-size: 16px !important; + } + + .ant-badge { + span { + color: @white; + } + } + + &:hover { + background-color: @header-dark-bg-hover-color; + } + } + } + } +} diff --git a/src/layouts/default/header/index.vue b/src/layouts/default/header/index.vue new file mode 100644 index 0000000..247ad4f --- /dev/null +++ b/src/layouts/default/header/index.vue @@ -0,0 +1,161 @@ + + + diff --git a/src/layouts/default/index.vue b/src/layouts/default/index.vue new file mode 100644 index 0000000..e0d64f0 --- /dev/null +++ b/src/layouts/default/index.vue @@ -0,0 +1,91 @@ + + + + diff --git a/src/layouts/default/menu/index.vue b/src/layouts/default/menu/index.vue new file mode 100644 index 0000000..833e946 --- /dev/null +++ b/src/layouts/default/menu/index.vue @@ -0,0 +1,196 @@ + + diff --git a/src/layouts/default/menu/useLayoutMenu.ts b/src/layouts/default/menu/useLayoutMenu.ts new file mode 100644 index 0000000..8a1044b --- /dev/null +++ b/src/layouts/default/menu/useLayoutMenu.ts @@ -0,0 +1,113 @@ +import type { Menu } from '@/router/types'; +import type { Ref } from 'vue'; +import { watch, unref, ref, computed } from 'vue'; +import { getChildrenMenus, getCurrentParentPath, getMenus, getShallowMenus } from '@/router/menus'; +import { useRouter } from 'vue-router'; +import { MenuSplitTyeEnum } from '@/enums/menuEnum'; +import { useThrottleFn } from '@vueuse/core'; +import { useMenuSetting } from '@/hooks/setting/useMenuSetting'; +import { usePermissionStore } from '@/store/modules/permission'; +import { useAppInject } from '@/hooks/web/useAppInject'; + +export function useSplitMenu(splitType: Ref) { + // Menu array + const menusRef = ref([]); + const { currentRoute } = useRouter(); + const { getIsMobile } = useAppInject(); + const permissionStore = usePermissionStore(); + const { setMenuSetting, getIsHorizontal, getSplit } = useMenuSetting(); + + const throttleHandleSplitLeftMenu = useThrottleFn(handleSplitLeftMenu, 50); + + const splitNotLeft = computed( + () => unref(splitType) !== MenuSplitTyeEnum.LEFT && !unref(getIsHorizontal), + ); + + const getSplitLeft = computed( + () => !unref(getSplit) || unref(splitType) !== MenuSplitTyeEnum.LEFT, + ); + + const getSpiltTop = computed(() => unref(splitType) === MenuSplitTyeEnum.TOP); + + const normalType = computed(() => { + return unref(splitType) === MenuSplitTyeEnum.NONE || !unref(getSplit); + }); + + watch( + [() => unref(currentRoute).path, () => unref(splitType)], + async ([path]: [string, MenuSplitTyeEnum]) => { + if (unref(splitNotLeft) || unref(getIsMobile)) return; + + const { meta } = unref(currentRoute); + const currentActiveMenu = meta.currentActiveMenu as string; + let parentPath = await getCurrentParentPath(path); + if (!parentPath) { + parentPath = await getCurrentParentPath(currentActiveMenu); + } + parentPath && throttleHandleSplitLeftMenu(parentPath); + }, + { + immediate: true, + }, + ); + + // Menu changes + watch( + [() => permissionStore.getLastBuildMenuTime, () => permissionStore.getBackMenuList], + () => { + genMenus(); + }, + { + immediate: true, + }, + ); + + // split Menu changes + watch( + () => getSplit.value, + () => { + if (unref(splitNotLeft)) return; + genMenus(); + }, + ); + watch(() => permissionStore.getChangeMenu, () => { + genMenus(); + }) + + // Handle left menu split + async function handleSplitLeftMenu(parentPath: string) { + if (unref(getSplitLeft) || unref(getIsMobile)) return; + + // spilt mode left + const children = await getChildrenMenus(parentPath); + + if (!children || !children.length) { + setMenuSetting({ hidden: true }); + menusRef.value = []; + return; + } + + setMenuSetting({ hidden: false }); + menusRef.value = children; + } + + // get menus + async function genMenus() { + // normal mode + if (unref(normalType) || unref(getIsMobile)) { + menusRef.value = await getMenus(); + // 11111 + return; + } + + // split-top + if (unref(getSpiltTop)) { + const shallowMenus = await getShallowMenus(); + + menusRef.value = shallowMenus; + return; + } + } + + return { menusRef }; +} diff --git a/src/layouts/default/setting/SettingDrawer.tsx b/src/layouts/default/setting/SettingDrawer.tsx new file mode 100644 index 0000000..8f6ca0f --- /dev/null +++ b/src/layouts/default/setting/SettingDrawer.tsx @@ -0,0 +1,435 @@ +import { defineComponent, computed, unref } from 'vue'; +import { BasicDrawer } from '@/components/Drawer'; +import { Divider } from 'ant-design-vue'; +import { + TypePicker, + ThemeColorPicker, + SettingFooter, + SwitchItem, + SelectItem, + InputNumberItem, +} from './components'; + +import { AppDarkModeToggle } from '@/components/Application'; + +import { MenuTypeEnum, TriggerEnum } from '@/enums/menuEnum'; + +import { useRootSetting } from '@/hooks/setting/useRootSetting'; +import { useMenuSetting } from '@/hooks/setting/useMenuSetting'; +import { useHeaderSetting } from '@/hooks/setting/useHeaderSetting'; +import { useMultipleTabSetting } from '@/hooks/setting/useMultipleTabSetting'; +import { useTransitionSetting } from '@/hooks/setting/useTransitionSetting'; +import { useI18n } from '@/hooks/web/useI18n'; + +import { baseHandler } from './handler'; + +import { + HandlerEnum, + contentModeOptions, + topMenuAlignOptions, + getMenuTriggerOptions, + routerTransitionOptions, + menuTypeListEnum, + mixSidebarTriggerOptions, +} from './enum'; + +// import { +// HEADER_PRESET_BG_COLOR_LIST, +// SIDE_BAR_BG_COLOR_LIST, +// APP_PRESET_COLOR_LIST, +// } from '@/settings/designSetting'; +import { SIDE_BAR_BG_COLOR_LIST } from '@/settings/designSetting'; + +const { t } = useI18n(); + +export default defineComponent({ + name: 'SettingDrawer', + setup(_, { attrs }) { + const { + getContentMode, + getShowFooter, + getShowBreadCrumb, + getShowBreadCrumbIcon, + getShowLogo, + getFullContent, + getColorWeak, + getGrayMode, + getLockTime, + getShowDarkModeToggle, + // getThemeColor, + } = useRootSetting(); + + const { getOpenPageLoading, getBasicTransition, getEnableTransition, getOpenNProgress } = + useTransitionSetting(); + + const { + getIsHorizontal, + getShowMenu, + getMenuType, + getTrigger, + getCollapsedShowTitle, + getMenuFixed, + getCollapsed, + getCanDrag, + getTopMenuAlign, + getAccordion, + getMenuWidth, + getMenuBgColor, + getIsTopMenu, + getSplit, + getIsMixSidebar, + getCloseMixSidebarOnChange, + getMixSideTrigger, + getMixSideFixed, + } = useMenuSetting(); + + const { + getShowHeader, + getFixed: getHeaderFixed, + // getHeaderBgColor, + getShowSearch, + } = useHeaderSetting(); + + const { getShowMultipleTab, getShowQuick, getShowRedo, getShowFold, getAutoCollapse } = + useMultipleTabSetting(); + + const getShowMenuRef = computed(() => { + return unref(getShowMenu) && !unref(getIsHorizontal); + }); + + function renderSidebar() { + return ( + <> + { + baseHandler(HandlerEnum.CHANGE_LAYOUT, { + mode: item.mode, + type: item.type, + split: unref(getIsHorizontal) ? false : undefined, + }); + }} + def={unref(getMenuType)} + /> + + ); + } + + // function renderHeaderTheme() { + // return ( + // + // ); + // } + + function renderSideBarTheme() { + return ( + + ); + } + + // function renderMainTheme() { + // return ( + // + // ); + // } + + /** + * @description: + */ + function renderFeatures() { + let triggerDef = unref(getTrigger); + + const triggerOptions = getMenuTriggerOptions(unref(getSplit)); + const some = triggerOptions.some((item) => item.value === triggerDef); + if (!some) { + triggerDef = TriggerEnum.FOOTER; + } + + return ( + <> + + + + + + + + + + + + + + + + + + + + { + return parseInt(value) === 0 + ? `0(${t('layout.setting.notAutoScreenLock')})` + : `${value}${t('layout.setting.minute')}`; + }} + /> + `${parseInt(value)}px`} + /> + + ); + } + + function renderContent() { + return ( + <> + + + + + + + + + + + + + + + + + + + + + + + ); + } + + function renderTransition() { + return ( + <> + + + + + + + + ); + } + + return () => ( + + {unref(getShowDarkModeToggle) && {() => t('layout.setting.darkMode')}} + {unref(getShowDarkModeToggle) && } + {() => t('layout.setting.navMode')} + {renderSidebar()} + {/* {() => t('layout.setting.sysTheme')} + {renderMainTheme()} + {() => t('layout.setting.headerTheme')} + {renderHeaderTheme()} */} + {() => t('layout.setting.sidebarTheme')} + {renderSideBarTheme()} + {() => t('layout.setting.interfaceFunction')} + {renderFeatures()} + {() => t('layout.setting.interfaceDisplay')} + {renderContent()} + {() => t('layout.setting.animation')} + {renderTransition()} + + + + ); + }, +}); diff --git a/src/layouts/default/setting/components/InputNumberItem.vue b/src/layouts/default/setting/components/InputNumberItem.vue new file mode 100644 index 0000000..09b9d3b --- /dev/null +++ b/src/layouts/default/setting/components/InputNumberItem.vue @@ -0,0 +1,49 @@ + + + diff --git a/src/layouts/default/setting/components/SelectItem.vue b/src/layouts/default/setting/components/SelectItem.vue new file mode 100644 index 0000000..ec866ed --- /dev/null +++ b/src/layouts/default/setting/components/SelectItem.vue @@ -0,0 +1,67 @@ + + + diff --git a/src/layouts/default/setting/components/SettingFooter.vue b/src/layouts/default/setting/components/SettingFooter.vue new file mode 100644 index 0000000..b61da43 --- /dev/null +++ b/src/layouts/default/setting/components/SettingFooter.vue @@ -0,0 +1,87 @@ + + + diff --git a/src/layouts/default/setting/components/SwitchItem.vue b/src/layouts/default/setting/components/SwitchItem.vue new file mode 100644 index 0000000..3e57893 --- /dev/null +++ b/src/layouts/default/setting/components/SwitchItem.vue @@ -0,0 +1,58 @@ + + + diff --git a/src/layouts/default/setting/components/ThemeColorPicker.vue b/src/layouts/default/setting/components/ThemeColorPicker.vue new file mode 100644 index 0000000..1e97150 --- /dev/null +++ b/src/layouts/default/setting/components/ThemeColorPicker.vue @@ -0,0 +1,81 @@ + + + diff --git a/src/layouts/default/setting/components/TypePicker.vue b/src/layouts/default/setting/components/TypePicker.vue new file mode 100644 index 0000000..6449bb2 --- /dev/null +++ b/src/layouts/default/setting/components/TypePicker.vue @@ -0,0 +1,172 @@ + + + diff --git a/src/layouts/default/setting/components/index.ts b/src/layouts/default/setting/components/index.ts new file mode 100644 index 0000000..e4910c6 --- /dev/null +++ b/src/layouts/default/setting/components/index.ts @@ -0,0 +1,8 @@ +import { createAsyncComponent } from '@/utils/factory/createAsyncComponent'; + +export const TypePicker = createAsyncComponent(() => import('./TypePicker.vue')); +export const ThemeColorPicker = createAsyncComponent(() => import('./ThemeColorPicker.vue')); +export const SettingFooter = createAsyncComponent(() => import('./SettingFooter.vue')); +export const SwitchItem = createAsyncComponent(() => import('./SwitchItem.vue')); +export const SelectItem = createAsyncComponent(() => import('./SelectItem.vue')); +export const InputNumberItem = createAsyncComponent(() => import('./InputNumberItem.vue')); diff --git a/src/layouts/default/setting/enum.ts b/src/layouts/default/setting/enum.ts new file mode 100644 index 0000000..3bc55f0 --- /dev/null +++ b/src/layouts/default/setting/enum.ts @@ -0,0 +1,157 @@ +import { ContentEnum, RouterTransitionEnum } from '@/enums/appEnum'; +import { + MenuModeEnum, + MenuTypeEnum, + TopMenuAlignEnum, + TriggerEnum, + MixSidebarTriggerEnum, +} from '@/enums/menuEnum'; + +import { useI18n } from '@/hooks/web/useI18n'; + +const { t } = useI18n(); + +export enum HandlerEnum { + CHANGE_LAYOUT, + CHANGE_THEME_COLOR, + CHANGE_THEME, + // menu + MENU_HAS_DRAG, + MENU_ACCORDION, + MENU_TRIGGER, + MENU_TOP_ALIGN, + MENU_COLLAPSED, + MENU_COLLAPSED_SHOW_TITLE, + MENU_WIDTH, + MENU_SHOW_SIDEBAR, + MENU_THEME, + MENU_SPLIT, + MENU_FIXED, + MENU_CLOSE_MIX_SIDEBAR_ON_CHANGE, + MENU_TRIGGER_MIX_SIDEBAR, + MENU_FIXED_MIX_SIDEBAR, + + // header + HEADER_SHOW, + HEADER_THEME, + HEADER_FIXED, + + HEADER_SEARCH, + + TABS_SHOW_QUICK, + TABS_SHOW_REDO, + TABS_SHOW, + TABS_SHOW_FOLD, + TABS_AUTO_COLLAPSE, + + LOCK_TIME, + FULL_CONTENT, + CONTENT_MODE, + SHOW_BREADCRUMB, + SHOW_BREADCRUMB_ICON, + GRAY_MODE, + COLOR_WEAK, + SHOW_LOGO, + SHOW_FOOTER, + + ROUTER_TRANSITION, + OPEN_PROGRESS, + OPEN_PAGE_LOADING, + OPEN_ROUTE_TRANSITION, +} + +export const contentModeOptions = [ + { + value: ContentEnum.FULL, + label: t('layout.setting.contentModeFull'), + }, + { + value: ContentEnum.FIXED, + label: t('layout.setting.contentModeFixed'), + }, +]; + +export const topMenuAlignOptions = [ + { + value: TopMenuAlignEnum.CENTER, + label: t('layout.setting.topMenuAlignRight'), + }, + { + value: TopMenuAlignEnum.START, + label: t('layout.setting.topMenuAlignLeft'), + }, + { + value: TopMenuAlignEnum.END, + label: t('layout.setting.topMenuAlignCenter'), + }, +]; + +export const getMenuTriggerOptions = (hideTop: boolean) => { + return [ + { + value: TriggerEnum.NONE, + label: t('layout.setting.menuTriggerNone'), + }, + { + value: TriggerEnum.FOOTER, + label: t('layout.setting.menuTriggerBottom'), + }, + ...(hideTop + ? [] + : [ + { + value: TriggerEnum.HEADER, + label: t('layout.setting.menuTriggerTop'), + }, + ]), + ]; +}; + +export const routerTransitionOptions = [ + RouterTransitionEnum.ZOOM_FADE, + RouterTransitionEnum.FADE, + RouterTransitionEnum.ZOOM_OUT, + RouterTransitionEnum.FADE_SIDE, + RouterTransitionEnum.FADE_BOTTOM, + RouterTransitionEnum.FADE_SCALE, +].map((item) => { + return { + label: item, + value: item, + }; +}); + +export const menuTypeListEnum = [ + { + title: t('layout.setting.menuTypeSidebar'), + mode: MenuModeEnum.INLINE, + type: MenuTypeEnum.SIDEBAR, + }, + { + title: t('layout.setting.menuTypeMix'), + mode: MenuModeEnum.INLINE, + type: MenuTypeEnum.MIX, + }, + + { + title: t('layout.setting.menuTypeTopMenu'), + mode: MenuModeEnum.HORIZONTAL, + type: MenuTypeEnum.TOP_MENU, + }, + { + title: t('layout.setting.menuTypeMixSidebar'), + mode: MenuModeEnum.INLINE, + type: MenuTypeEnum.MIX_SIDEBAR, + }, +]; + +export const mixSidebarTriggerOptions = [ + { + value: MixSidebarTriggerEnum.HOVER, + label: t('layout.setting.triggerHover'), + }, + { + value: MixSidebarTriggerEnum.CLICK, + label: t('layout.setting.triggerClick'), + }, +]; diff --git a/src/layouts/default/setting/handler.ts b/src/layouts/default/setting/handler.ts new file mode 100644 index 0000000..8028cb2 --- /dev/null +++ b/src/layouts/default/setting/handler.ts @@ -0,0 +1,182 @@ +import { MenuTypeEnum } from '@/enums/menuEnum'; +import { HandlerEnum } from './enum'; +import { updateHeaderBgColor, updateSidebarBgColor } from '@/logics/theme/updateBackground'; +import { updateColorWeak } from '@/logics/theme/updateColorWeak'; +import { updateGrayMode } from '@/logics/theme/updateGrayMode'; + +import { useAppStore } from '@/store/modules/app'; +import { ProjectConfig } from '#/config'; +import { updateDarkTheme } from '@/logics/theme/dark'; +import { useRootSetting } from '@/hooks/setting/useRootSetting'; +import projectSetting from '@/settings/projectSetting'; + +export function baseHandler(event: HandlerEnum, value: any) { + const appStore = useAppStore(); + const config = handler(event, value); + appStore.setProjectConfig(config); + if (event === HandlerEnum.CHANGE_THEME) { + updateHeaderBgColor(); + updateSidebarBgColor(); + } +} + +export function handler(event: HandlerEnum, value: any): DeepPartial { + const appStore = useAppStore(); + + const { getThemeColor, getDarkMode } = useRootSetting(); + const { menuSetting } = projectSetting; + switch (event) { + case HandlerEnum.CHANGE_LAYOUT: + const { mode, type, split } = value; + const isMixSidebar = type === MenuTypeEnum.MIX; + const mixSideSplitOpt = + menuSetting.type === MenuTypeEnum.MIX ? { split: menuSetting.split } : { split }; + const otherSplitOpt = { split: false }; + const splitOpt = isMixSidebar ? mixSideSplitOpt : otherSplitOpt; + + return { + menuSetting: { + mode, + type, + collapsed: false, + show: true, + hidden: false, + ...splitOpt, + }, + }; + + case HandlerEnum.CHANGE_THEME_COLOR: + if (getThemeColor.value === value) { + return {}; + } + + return { themeColor: value }; + + case HandlerEnum.CHANGE_THEME: + if (getDarkMode.value === value) { + return {}; + } + updateDarkTheme(value); + + return {}; + + case HandlerEnum.MENU_HAS_DRAG: + return { menuSetting: { canDrag: value } }; + + case HandlerEnum.MENU_ACCORDION: + return { menuSetting: { accordion: value } }; + + case HandlerEnum.MENU_TRIGGER: + return { menuSetting: { trigger: value } }; + + case HandlerEnum.MENU_TOP_ALIGN: + return { menuSetting: { topMenuAlign: value } }; + + case HandlerEnum.MENU_COLLAPSED: + return { menuSetting: { collapsed: value } }; + + case HandlerEnum.MENU_WIDTH: + return { menuSetting: { menuWidth: value } }; + + case HandlerEnum.MENU_SHOW_SIDEBAR: + return { menuSetting: { show: value } }; + + case HandlerEnum.MENU_COLLAPSED_SHOW_TITLE: + return { menuSetting: { collapsedShowTitle: value } }; + + case HandlerEnum.MENU_THEME: + updateSidebarBgColor(value); + return { menuSetting: { bgColor: value } }; + + case HandlerEnum.MENU_SPLIT: + return { menuSetting: { split: value } }; + + case HandlerEnum.MENU_CLOSE_MIX_SIDEBAR_ON_CHANGE: + return { menuSetting: { closeMixSidebarOnChange: value } }; + + case HandlerEnum.MENU_FIXED: + return { menuSetting: { fixed: value } }; + + case HandlerEnum.MENU_TRIGGER_MIX_SIDEBAR: + return { menuSetting: { mixSideTrigger: value } }; + + case HandlerEnum.MENU_FIXED_MIX_SIDEBAR: + return { menuSetting: { mixSideFixed: value } }; + + // ============transition================== + case HandlerEnum.OPEN_PAGE_LOADING: + appStore.setPageLoading(false); + return { transitionSetting: { openPageLoading: value } }; + + case HandlerEnum.ROUTER_TRANSITION: + return { transitionSetting: { basicTransition: value } }; + + case HandlerEnum.OPEN_ROUTE_TRANSITION: + return { transitionSetting: { enable: value } }; + + case HandlerEnum.OPEN_PROGRESS: + return { transitionSetting: { openNProgress: value } }; + // ============root================== + + case HandlerEnum.LOCK_TIME: + return { lockTime: value }; + + case HandlerEnum.FULL_CONTENT: + return { fullContent: value }; + + case HandlerEnum.CONTENT_MODE: + return { contentMode: value }; + + case HandlerEnum.SHOW_BREADCRUMB: + return { showBreadCrumb: value }; + + case HandlerEnum.SHOW_BREADCRUMB_ICON: + return { showBreadCrumbIcon: value }; + + case HandlerEnum.GRAY_MODE: + updateGrayMode(value); + return { grayMode: value }; + + case HandlerEnum.SHOW_FOOTER: + return { showFooter: value }; + + case HandlerEnum.COLOR_WEAK: + updateColorWeak(value); + return { colorWeak: value }; + + case HandlerEnum.SHOW_LOGO: + return { showLogo: value }; + + // ============tabs================== + case HandlerEnum.TABS_SHOW_QUICK: + return { multiTabsSetting: { showQuick: value } }; + + case HandlerEnum.TABS_SHOW: + return { multiTabsSetting: { show: value } }; + + case HandlerEnum.TABS_SHOW_REDO: + return { multiTabsSetting: { showRedo: value } }; + + case HandlerEnum.TABS_SHOW_FOLD: + return { multiTabsSetting: { showFold: value } }; + + case HandlerEnum.TABS_AUTO_COLLAPSE: + return { multiTabsSetting: { autoCollapse: value } }; + + // ============header================== + case HandlerEnum.HEADER_THEME: + updateHeaderBgColor(value); + return { headerSetting: { bgColor: value } }; + + case HandlerEnum.HEADER_SEARCH: + return { headerSetting: { showSearch: value } }; + + case HandlerEnum.HEADER_FIXED: + return { headerSetting: { fixed: value } }; + + case HandlerEnum.HEADER_SHOW: + return { headerSetting: { show: value } }; + default: + return {}; + } +} diff --git a/src/layouts/default/setting/index.vue b/src/layouts/default/setting/index.vue new file mode 100644 index 0000000..26fda4a --- /dev/null +++ b/src/layouts/default/setting/index.vue @@ -0,0 +1,16 @@ + + diff --git a/src/layouts/default/sider/DragBar.vue b/src/layouts/default/sider/DragBar.vue new file mode 100644 index 0000000..1b988b7 --- /dev/null +++ b/src/layouts/default/sider/DragBar.vue @@ -0,0 +1,58 @@ + + + diff --git a/src/layouts/default/sider/LayoutSider.vue b/src/layouts/default/sider/LayoutSider.vue new file mode 100644 index 0000000..7fd712f --- /dev/null +++ b/src/layouts/default/sider/LayoutSider.vue @@ -0,0 +1,157 @@ + + + diff --git a/src/layouts/default/sider/MixSider.vue b/src/layouts/default/sider/MixSider.vue new file mode 100644 index 0000000..b73e79d --- /dev/null +++ b/src/layouts/default/sider/MixSider.vue @@ -0,0 +1,567 @@ + + + diff --git a/src/layouts/default/sider/index.vue b/src/layouts/default/sider/index.vue new file mode 100644 index 0000000..4abbf56 --- /dev/null +++ b/src/layouts/default/sider/index.vue @@ -0,0 +1,51 @@ + + + + diff --git a/src/layouts/default/sider/useLayoutSider.ts b/src/layouts/default/sider/useLayoutSider.ts new file mode 100644 index 0000000..8077b65 --- /dev/null +++ b/src/layouts/default/sider/useLayoutSider.ts @@ -0,0 +1,143 @@ +import type { Ref } from 'vue'; + +import { computed, unref, onMounted, nextTick } from 'vue'; + +import { TriggerEnum } from '@/enums/menuEnum'; + +import { useMenuSetting } from '@/hooks/setting/useMenuSetting'; +import { useDebounceFn } from '@vueuse/core'; +import { useAppStore } from '@/store/modules/app'; + +/** + * Handle related operations of menu events + */ +export function useSiderEvent() { + const appStore = useAppStore(); + const { getMiniWidthNumber } = useMenuSetting(); + + const getCollapsedWidth = computed(() => { + return unref(getMiniWidthNumber); + }); + + function onBreakpointChange(broken: boolean) { + appStore.setProjectConfig({ + menuSetting: { + siderHidden: broken, + }, + }); + } + + return { getCollapsedWidth, onBreakpointChange }; +} + +/** + * Handle related operations of menu folding + */ +export function useTrigger(getIsMobile: Ref) { + const { getTrigger, getSplit } = useMenuSetting(); + + const getShowTrigger = computed(() => { + const trigger = unref(getTrigger); + + return ( + trigger !== TriggerEnum.NONE && + !unref(getIsMobile) && + (trigger === TriggerEnum.FOOTER || unref(getSplit)) + ); + }); + + const getTriggerAttr = computed(() => { + if (unref(getShowTrigger)) { + return {}; + } + return { + trigger: null, + }; + }); + + return { getTriggerAttr, getShowTrigger }; +} + +/** + * Handle menu drag and drop related operations + * @param siderRef + * @param dragBarRef + */ +export function useDragLine(siderRef: Ref, dragBarRef: Ref, mix = false) { + const { getMiniWidthNumber, getCollapsed, setMenuSetting } = useMenuSetting(); + + onMounted(() => { + nextTick(() => { + const exec = useDebounceFn(changeWrapWidth, 80); + exec(); + }); + }); + + function getEl(elRef: Ref): any { + const el = unref(elRef); + if (!el) return null; + if (Reflect.has(el, '$el')) { + return (unref(elRef) as ComponentRef)?.$el; + } + return unref(elRef); + } + + function handleMouseMove(ele: HTMLElement, wrap: HTMLElement, clientX: number) { + document.onmousemove = function (innerE) { + let iT = (ele as any).left + (innerE.clientX - clientX); + innerE = innerE || window.event; + const maxT = 800; + const minT = unref(getMiniWidthNumber); + iT < 0 && (iT = 0); + iT > maxT && (iT = maxT); + iT < minT && (iT = minT); + ele.style.left = wrap.style.width = iT + 'px'; + return false; + }; + } + + // Drag and drop in the menu area-release the mouse + function removeMouseup(ele: any) { + const wrap = getEl(siderRef); + document.onmouseup = function () { + document.onmousemove = null; + document.onmouseup = null; + wrap.style.transition = 'width 0.2s'; + const width = parseInt(wrap.style.width); + + if (!mix) { + const miniWidth = unref(getMiniWidthNumber); + if (!unref(getCollapsed)) { + width > miniWidth + 20 + ? setMenuSetting({ menuWidth: width }) + : setMenuSetting({ collapsed: true }); + } else { + width > miniWidth && setMenuSetting({ collapsed: false, menuWidth: width }); + } + } else { + setMenuSetting({ menuWidth: width }); + } + + ele.releaseCapture?.(); + }; + } + + function changeWrapWidth() { + const ele = getEl(dragBarRef); + if (!ele) return; + const wrap = getEl(siderRef); + if (!wrap) return; + + ele.onmousedown = (e: any) => { + wrap.style.transition = 'unset'; + const clientX = e?.clientX; + ele.left = ele.offsetLeft; + handleMouseMove(ele, wrap, clientX); + removeMouseup(ele); + ele.setCapture?.(); + return false; + }; + } + + return {}; +} diff --git a/src/layouts/default/tabs/components/FoldButton.vue b/src/layouts/default/tabs/components/FoldButton.vue new file mode 100644 index 0000000..7030e3a --- /dev/null +++ b/src/layouts/default/tabs/components/FoldButton.vue @@ -0,0 +1,36 @@ + + diff --git a/src/layouts/default/tabs/components/SettingButton.vue b/src/layouts/default/tabs/components/SettingButton.vue new file mode 100644 index 0000000..baf566f --- /dev/null +++ b/src/layouts/default/tabs/components/SettingButton.vue @@ -0,0 +1,19 @@ + + diff --git a/src/layouts/default/tabs/components/TabContent.vue b/src/layouts/default/tabs/components/TabContent.vue new file mode 100644 index 0000000..c7b42b2 --- /dev/null +++ b/src/layouts/default/tabs/components/TabContent.vue @@ -0,0 +1,63 @@ + + diff --git a/src/layouts/default/tabs/components/TabRedo.vue b/src/layouts/default/tabs/components/TabRedo.vue new file mode 100644 index 0000000..bc39262 --- /dev/null +++ b/src/layouts/default/tabs/components/TabRedo.vue @@ -0,0 +1,32 @@ + + + diff --git a/src/layouts/default/tabs/index.less b/src/layouts/default/tabs/index.less new file mode 100644 index 0000000..38c9a13 --- /dev/null +++ b/src/layouts/default/tabs/index.less @@ -0,0 +1,222 @@ +@prefix-cls: ~'@{namespace}-multiple-tabs'; +@prefix-cls-default-layout: ~'@{namespace}-default-layout'; + +html[data-theme='light'] { + .@{prefix-cls} { + .ant-tabs-tab:not(.ant-tabs-tab-active) { + border: 1px solid #d9d9d9 !important; + border-bottom-color: #f0f0f0 !important; + } + } +} + +.@{prefix-cls-default-layout}-out { + &.ant-layout-auto-collapse-tabs { + .@{prefix-cls} { + margin-top: -(@multiple-height + 2); + opacity: 0.1; + + &:hover, + &--hover { + margin-top: 0; + transition-delay: 0s; + opacity: 1; + } + } + } + .@{prefix-cls} { + transition: + margin 0.2s ease-in-out 0.6s, + opacity 0.2s ease-in-out 0.6s; + } +} + +.@{prefix-cls} { + z-index: 10; + height: @multiple-height + 2; + border-bottom: 1px solid @border-color-base; + background-color: @component-background; + line-height: @multiple-height + 2; + + .ant-tabs-small { + height: @multiple-height; + } + + .ant-tabs.ant-tabs-card { + .ant-tabs-nav { + height: @multiple-height + 2; + margin: 0; + padding-top: 2px; + border: 0; + background-color: @component-background; + box-shadow: none; + + .ant-tabs-nav-container { + height: @multiple-height; + padding-top: 2px; + } + + .ant-tabs-tab { + height: calc(@multiple-height); + padding-right: 12px; + transition: none; + background-color: @component-background; + color: @text-color-base; + line-height: calc(@multiple-height); + + &:hover { + .ant-tabs-tab-remove { + opacity: 1; + } + } + + .ant-tabs-tab-remove { + width: 8px; + height: 28px; + margin-right: -4px; + margin-left: 2px; + transition: none; + opacity: 0; + color: inherit; + font-size: 12px; + + &:hover { + svg { + width: 0.8em; + } + } + } + + // > div { + // display: flex; + // justify-content: center; + // align-items: center; + // } + + svg { + fill: @text-color-base; + } + } + + .ant-tabs-tab:not(.ant-tabs-tab-active) { + &:hover { + color: @primary-color; + } + } + + .ant-tabs-tab-active { + position: relative; + padding-left: 18px; + transition: none; + border: 0; + background: @primary-color; + + span { + color: @white !important; + } + + .ant-tabs-tab-remove { + opacity: 1; + } + + svg { + width: 0.7em; + fill: @white; + } + } + } + + .ant-tabs-nav > div:nth-child(1) { + padding: 0 6px; + + .ant-tabs-tab { + margin-right: 3px !important; + } + } + } + + .ant-tabs-tab:not(.ant-tabs-tab-active) { + .anticon-close { + font-size: 12px; + + svg { + width: 0.6em; + } + } + } + + .ant-dropdown-trigger { + display: inline-flex; + } + + &--hide-close { + .ant-tabs-tab-remove { + opacity: 0 !important; + } + } + + &-content { + &__extra-quick, + &__extra-redo, + &__extra-fold { + display: inline-block; + width: 36px; + height: @multiple-height; + border-left: 1px solid @border-color-base; + color: @text-color-secondary; + line-height: @multiple-height; + text-align: center; + cursor: pointer; + + &:hover { + color: @text-color-base; + } + + span[role='img'] { + transform: rotate(90deg); + } + } + + &__extra-redo { + span[role='img'] { + transform: rotate(0deg); + } + } + + &__info { + display: inline-block; + width: 100%; + height: @multiple-height - 2; + margin-left: -10px; + padding-left: 0; + font-size: 12px; + cursor: pointer; + user-select: none; + } + } +} + +.ant-tabs-dropdown-menu { + &-title-content { + display: flex; + align-items: center; + + .@{prefix-cls} { + &-content__info { + width: auto; + margin-left: 0; + line-height: 28px; + } + } + } + + &-item-remove { + margin-left: auto; + } +} + +.multiple-tabs__dropdown { + .ant-dropdown-content { + width: 172px; + } +} diff --git a/src/layouts/default/tabs/index.vue b/src/layouts/default/tabs/index.vue new file mode 100644 index 0000000..189a1b0 --- /dev/null +++ b/src/layouts/default/tabs/index.vue @@ -0,0 +1,137 @@ + + + diff --git a/src/layouts/default/tabs/types.ts b/src/layouts/default/tabs/types.ts new file mode 100644 index 0000000..30539c1 --- /dev/null +++ b/src/layouts/default/tabs/types.ts @@ -0,0 +1,25 @@ +import type { DropMenu } from '@/components/Dropdown'; +import type { RouteLocationNormalized } from 'vue-router'; + +export enum TabContentEnum { + TAB_TYPE, + EXTRA_TYPE, +} + +export type { DropMenu }; + +export interface TabContentProps { + tabItem: RouteLocationNormalized; + type?: TabContentEnum; + trigger?: ('click' | 'hover' | 'contextmenu')[]; +} + +export enum MenuEventEnum { + REFRESH_PAGE, + CLOSE_CURRENT, + CLOSE_LEFT, + CLOSE_RIGHT, + CLOSE_OTHER, + CLOSE_ALL, + SCALE, +} diff --git a/src/layouts/default/tabs/useMultipleTabs.ts b/src/layouts/default/tabs/useMultipleTabs.ts new file mode 100644 index 0000000..70cac1c --- /dev/null +++ b/src/layouts/default/tabs/useMultipleTabs.ts @@ -0,0 +1,83 @@ +import { toRaw, ref, nextTick } from 'vue'; +import type { RouteLocationNormalized } from 'vue-router'; +import { useDesign } from '@/hooks/web/useDesign'; +import { useSortable } from '@/hooks/web/useSortable'; +import { useMultipleTabStore } from '@/store/modules/multipleTab'; +import { isNil } from '@/utils/is'; +import projectSetting from '@/settings/projectSetting'; +import { useRouter } from 'vue-router'; +import { useI18n } from '@/hooks/web/useI18n'; + +const { t } = useI18n(); + +export function initAffixTabs(): string[] { + const affixList = ref([]); + + const tabStore = useMultipleTabStore(); + const router = useRouter(); + /** + * @description: Filter all fixed routes + */ + function filterAffixTabs(routes: RouteLocationNormalized[]) { + const tabs: RouteLocationNormalized[] = []; + routes && + routes.forEach((route) => { + if (route.meta && route.meta.affix) { + tabs.push(toRaw(route)); + } + }); + return tabs; + } + + /** + * @description: Set fixed tabs + */ + function addAffixTabs(): void { + const affixTabs = filterAffixTabs(router.getRoutes() as unknown as RouteLocationNormalized[]); + affixList.value = affixTabs; + for (const tab of affixTabs) { + tabStore.addTab({ + meta: tab.meta, + name: tab.name, + path: tab.path, + } as unknown as RouteLocationNormalized); + } + } + + let isAddAffix = false; + + if (!isAddAffix) { + addAffixTabs(); + isAddAffix = true; + } + return affixList.value.map((item) => item.meta?.title).filter(Boolean) as string[]; +} + +export function useTabsDrag(affixTextList: string[]) { + const tabStore = useMultipleTabStore(); + const { multiTabsSetting } = projectSetting; + const { prefixCls } = useDesign('multiple-tabs'); + nextTick(() => { + if (!multiTabsSetting.canDrag) return; + const el = document.querySelectorAll( + `.${prefixCls} .ant-tabs-nav-wrap > div`, + )?.[0] as HTMLElement; + const { initSortable } = useSortable(el, { + filter: (_evt, target: HTMLElement) => { + const text = target.innerText; + if (!text) return false; + return affixTextList.map((res) => t(res)).includes(text); + }, + onEnd: (evt) => { + const { oldIndex, newIndex } = evt; + + if (isNil(oldIndex) || isNil(newIndex) || oldIndex === newIndex) { + return; + } + + tabStore.sortTabs(oldIndex, newIndex); + }, + }); + initSortable(); + }); +} diff --git a/src/layouts/default/tabs/useTabDropdown.ts b/src/layouts/default/tabs/useTabDropdown.ts new file mode 100644 index 0000000..8c8e843 --- /dev/null +++ b/src/layouts/default/tabs/useTabDropdown.ts @@ -0,0 +1,140 @@ +import type { TabContentProps } from './types'; +import type { DropMenu } from '@/components/Dropdown'; +import type { ComputedRef } from 'vue'; + +import { computed, unref, reactive } from 'vue'; +import { MenuEventEnum } from './types'; +import { useMultipleTabStore } from '@/store/modules/multipleTab'; +import { RouteLocationNormalized, useRouter } from 'vue-router'; +import { useTabs } from '@/hooks/web/useTabs'; +import { useI18n } from '@/hooks/web/useI18n'; + +export function useTabDropdown(tabContentProps: TabContentProps, getIsTabs: ComputedRef) { + const state = reactive({ + current: null as Nullable, + currentIndex: 0, + }); + + const { t } = useI18n(); + const tabStore = useMultipleTabStore(); + const { currentRoute } = useRouter(); + const { refreshPage, closeAll, close, closeLeft, closeOther, closeRight } = useTabs(); + + const getTargetTab = computed((): RouteLocationNormalized => { + return unref(getIsTabs) ? tabContentProps.tabItem : unref(currentRoute); + }); + + /** + * @description: drop-down list + */ + const getDropMenuList = computed(() => { + if (!unref(getTargetTab)) { + return; + } + const { meta } = unref(getTargetTab); + const { path } = unref(currentRoute); + + const curItem = state.current; + + const isCurItem = curItem ? curItem.path === path : false; + + // Refresh button + const index = state.currentIndex; + const refreshDisabled = !isCurItem; + // Close left + const closeLeftDisabled = index === 0 || !isCurItem; + + const disabled = tabStore.getTabList.length === 1; + + // Close right + const closeRightDisabled = + !isCurItem || (index === tabStore.getTabList.length - 1 && tabStore.getLastDragEndIndex >= 0); + const dropMenuList: DropMenu[] = [ + { + icon: 'ion:reload-sharp', + event: MenuEventEnum.REFRESH_PAGE, + text: t('layout.multipleTab.reload'), + disabled: refreshDisabled, + }, + { + icon: 'clarity:close-line', + event: MenuEventEnum.CLOSE_CURRENT, + text: t('layout.multipleTab.close'), + disabled: !!meta?.affix || disabled, + divider: true, + }, + { + icon: 'line-md:arrow-close-left', + event: MenuEventEnum.CLOSE_LEFT, + text: t('layout.multipleTab.closeLeft'), + disabled: closeLeftDisabled, + divider: false, + }, + { + icon: 'line-md:arrow-close-right', + event: MenuEventEnum.CLOSE_RIGHT, + text: t('layout.multipleTab.closeRight'), + disabled: closeRightDisabled, + divider: true, + }, + { + icon: 'dashicons:align-center', + event: MenuEventEnum.CLOSE_OTHER, + text: t('layout.multipleTab.closeOther'), + disabled: disabled || !isCurItem, + }, + { + icon: 'clarity:minus-line', + event: MenuEventEnum.CLOSE_ALL, + text: t('layout.multipleTab.closeAll'), + disabled: disabled, + }, + ]; + + return dropMenuList; + }); + + function handleContextMenu(tabItem: RouteLocationNormalized) { + return (e: Event) => { + if (!tabItem) { + return; + } + e?.preventDefault(); + const index = tabStore.getTabList.findIndex((tab) => tab.path === tabItem.path); + state.current = tabItem; + state.currentIndex = index; + }; + } + + // Handle right click event + function handleMenuEvent(menu: DropMenu): void { + const { event } = menu; + switch (event) { + case MenuEventEnum.REFRESH_PAGE: + // refresh page + refreshPage(); + break; + // Close current + case MenuEventEnum.CLOSE_CURRENT: + close(tabContentProps.tabItem); + break; + // Close left + case MenuEventEnum.CLOSE_LEFT: + closeLeft(); + break; + // Close right + case MenuEventEnum.CLOSE_RIGHT: + closeRight(); + break; + // Close other + case MenuEventEnum.CLOSE_OTHER: + closeOther(); + break; + // Close all + case MenuEventEnum.CLOSE_ALL: + closeAll(); + break; + } + } + return { getDropMenuList, handleMenuEvent, handleContextMenu }; +} diff --git a/src/layouts/default/trigger/HeaderTrigger.vue b/src/layouts/default/trigger/HeaderTrigger.vue new file mode 100644 index 0000000..364aa64 --- /dev/null +++ b/src/layouts/default/trigger/HeaderTrigger.vue @@ -0,0 +1,17 @@ + + diff --git a/src/layouts/default/trigger/SiderTrigger.vue b/src/layouts/default/trigger/SiderTrigger.vue new file mode 100644 index 0000000..0af0872 --- /dev/null +++ b/src/layouts/default/trigger/SiderTrigger.vue @@ -0,0 +1,12 @@ + + diff --git a/src/layouts/default/trigger/index.vue b/src/layouts/default/trigger/index.vue new file mode 100644 index 0000000..2a030d9 --- /dev/null +++ b/src/layouts/default/trigger/index.vue @@ -0,0 +1,15 @@ + + + diff --git a/src/layouts/iframe/index.vue b/src/layouts/iframe/index.vue new file mode 100644 index 0000000..da96579 --- /dev/null +++ b/src/layouts/iframe/index.vue @@ -0,0 +1,23 @@ + + diff --git a/src/layouts/iframe/useFrameKeepAlive.ts b/src/layouts/iframe/useFrameKeepAlive.ts new file mode 100644 index 0000000..2c295cc --- /dev/null +++ b/src/layouts/iframe/useFrameKeepAlive.ts @@ -0,0 +1,59 @@ +import type { AppRouteRecordRaw } from '@/router/types'; + +import { computed, toRaw, unref } from 'vue'; + +import { useMultipleTabStore } from '@/store/modules/multipleTab'; + +import { uniqBy } from 'lodash-es'; + +import { useMultipleTabSetting } from '@/hooks/setting/useMultipleTabSetting'; + +import { useRouter } from 'vue-router'; + +export function useFrameKeepAlive() { + const router = useRouter(); + const { currentRoute } = router; + const { getShowMultipleTab } = useMultipleTabSetting(); + const tabStore = useMultipleTabStore(); + const getFramePages = computed(() => { + const ret = getAllFramePages(toRaw(router.getRoutes()) as unknown as AppRouteRecordRaw[]) || []; + return ret; + }); + + const getOpenTabList = computed((): string[] => { + return tabStore.getTabList.reduce((prev: string[], next) => { + if (next.meta && Reflect.has(next.meta, 'frameSrc')) { + prev.push(next.name as string); + } + return prev; + }, []); + }); + + function getAllFramePages(routes: AppRouteRecordRaw[]): AppRouteRecordRaw[] { + let res: AppRouteRecordRaw[] = []; + for (const route of routes) { + const { meta: { frameSrc } = {}, children } = route; + if (frameSrc) { + res.push(route); + } + if (children && children.length) { + res.push(...getAllFramePages(children)); + } + } + res = uniqBy(res, 'name'); + return res; + } + + function showIframe(item: AppRouteRecordRaw) { + return item.name === unref(currentRoute).name; + } + + function hasRenderFrame(name: string) { + if (!unref(getShowMultipleTab)) { + return router.currentRoute.value.name === name; + } + return unref(getOpenTabList).includes(name); + } + + return { hasRenderFrame, getFramePages, showIframe, getAllFramePages }; +} diff --git a/src/layouts/page/index.vue b/src/layouts/page/index.vue new file mode 100644 index 0000000..a4bf480 --- /dev/null +++ b/src/layouts/page/index.vue @@ -0,0 +1,56 @@ + + + diff --git a/src/layouts/page/transition.ts b/src/layouts/page/transition.ts new file mode 100644 index 0000000..9e93009 --- /dev/null +++ b/src/layouts/page/transition.ts @@ -0,0 +1,33 @@ +import type { FunctionalComponent } from 'vue'; +import type { RouteLocation } from 'vue-router'; + +export interface DefaultContext { + Component: FunctionalComponent & { type: Recordable }; + route: RouteLocation; +} + +export function getTransitionName({ + route, + openCache, + cacheTabs, + enableTransition, + def, +}: Pick & { + enableTransition: boolean; + openCache: boolean; + def: string; + cacheTabs: string[]; +}): string | undefined { + if (!enableTransition) { + return undefined; + } + + const isInCache = cacheTabs.includes(route.name as string); + const transitionName = 'fade-slide'; + let name: string | undefined = transitionName; + + if (openCache) { + name = isInCache && route.meta.loaded ? transitionName : undefined; + } + return name || (route.meta.transitionName as string) || def; +} diff --git a/src/locales/helper.ts b/src/locales/helper.ts new file mode 100644 index 0000000..6c70c4c --- /dev/null +++ b/src/locales/helper.ts @@ -0,0 +1,37 @@ +import type { LocaleType } from '#/config'; + +import { set } from 'lodash-es'; + +export const loadLocalePool: LocaleType[] = []; + +export function setHtmlPageLang(locale: LocaleType) { + document.querySelector('html')?.setAttribute('lang', locale); +} + +export function setLoadLocalePool(cb: (loadLocalePool: LocaleType[]) => void) { + cb(loadLocalePool); +} + +export function genMessage(langs: Record>, prefix = 'lang') { + const obj: Recordable = {}; + + Object.keys(langs).forEach((key) => { + const langFileModule = langs[key].default; + let fileName = key.replace(`./${prefix}/`, '').replace(/^\.\//, ''); + const lastIndex = fileName.lastIndexOf('.'); + fileName = fileName.substring(0, lastIndex); + const keyList = fileName.split('/'); + const moduleName = keyList.shift(); + const objKey = keyList.join('.'); + + if (moduleName) { + if (objKey) { + set(obj, moduleName, obj[moduleName] || {}); + set(obj[moduleName], objKey, langFileModule); + } else { + set(obj, moduleName, langFileModule || {}); + } + } + }); + return obj; +} diff --git a/src/locales/lang/en.ts b/src/locales/lang/en.ts new file mode 100644 index 0000000..a25bf56 --- /dev/null +++ b/src/locales/lang/en.ts @@ -0,0 +1,12 @@ +import { genMessage } from '../helper'; +import antdLocale from 'ant-design-vue/es/locale/en_US'; + +const modules = import.meta.glob('./en/**/*.json', { eager: true }); +export default { + message: { + ...genMessage(modules as Recordable, 'en'), + antdLocale, + }, + dateLocale: null, + dateLocaleName: 'en', +}; diff --git a/src/locales/lang/en/common.json b/src/locales/lang/en/common.json new file mode 100644 index 0000000..e0e73f8 --- /dev/null +++ b/src/locales/lang/en/common.json @@ -0,0 +1,17 @@ +{ + "okText": "OK", + "closeText": "Close", + "cancelText": "Cancel", + "loadingText": "Loading...", + "saveText": "Save", + "delText": "Delete", + "resetText": "Reset", + "searchText": "Search", + "queryText": "Search", + "inputText": "Please enter ", + "chooseText": "Please choose ", + "redo": "Refresh", + "back": "Back", + "light": "Light", + "dark": "Dark" +} diff --git a/src/locales/lang/en/component.json b/src/locales/lang/en/component.json new file mode 100644 index 0000000..1174118 --- /dev/null +++ b/src/locales/lang/en/component.json @@ -0,0 +1,128 @@ +{ + "app": { + "searchNotData": "No search results yet", + "toSearch": "to search", + "toNavigate": "to navigate" + }, + "countdown": { + "normalText": "Get SMS code", + "sendText": "Reacquire in {0}s" + }, + "cropper": { + "selectImage": "Select Image", + "uploadSuccess": "Uploaded success!", + "imageTooBig": "Image too big", + "modalTitle": "Avatar upload", + "okText": "Confirm and upload", + "btn_reset": "Reset", + "btn_rotate_left": "Counterclockwise rotation", + "btn_rotate_right": "Clockwise rotation", + "btn_scale_x": "Flip horizontal", + "btn_scale_y": "Flip vertical", + "btn_zoom_in": "Zoom in", + "btn_zoom_out": "Zoom out", + "preview": "Preivew" + }, + "drawer": { + "loadingText": "Loading...", + "cancelText": "Close", + "okText": "Confirm" + }, + "excel": { + "exportModalTitle": "Export data", + "fileType": "File type", + "fileName": "File name" + }, + "form": { + "putAway": "Put away", + "unfold": "Unfold", + "maxTip": "The number of characters should be less than {0}", + "apiSelectNotFound": "Wait for data loading to complete..." + }, + "icon": { + "placeholder": "Click the select icon", + "search": "Search icon", + "copy": "Copy icon successfully!" + }, + "menu": { + "search": "Menu search" + }, + "modal": { + "cancelText": "Close", + "okText": "Confirm", + "close": "Close", + "maximize": "Maximize", + "restore": "Restore" + }, + "table": { + "settingDens": "Density", + "settingDensDefault": "Default", + "settingDensMiddle": "Middle", + "settingDensSmall": "Compact", + "settingColumn": "Column settings", + "settingColumnShow": "Column display", + "settingIndexColumnShow": "Index Column", + "settingSelectColumnShow": "Selection Column", + "settingFixedLeft": "Fixed Left", + "settingFixedRight": "Fixed Right", + "settingFullScreen": "Full Screen", + "index": "Index", + "total": "total of {total}", + "selectionBarTips": "{count} records selected.", + "selectionBarClear": "Clear", + "selectionBarEmpty": "No records selected." + }, + "time": { + "before": " ago", + "after": " after", + "just": "just now", + "seconds": " seconds", + "minutes": " minutes", + "hours": " hours", + "days": " days" + }, + "tree": { + "selectAll": "Select All", + "unSelectAll": "Cancel Select", + "expandAll": "Expand All", + "unExpandAll": "Collapse all", + "checkStrictly": "Hierarchical association", + "checkUnStrictly": "Hierarchical independence" + }, + "upload": { + "save": "Save", + "upload": "Upload", + "imgUpload": "ImageUpload", + "uploaded": "Uploaded", + "operating": "Operating", + "del": "Delete", + "download": "download", + "saveWarn": "Please wait for the file to upload and save!", + "saveError": "There is no file successfully uploaded and cannot be saved!", + "preview": "Preview", + "choose": "Select the file", + "accept": "Support {0} format", + "acceptUpload": "Only upload files in {0} format", + "maxSize": "A single file does not exceed {0}MB ", + "maxSizeMultiple": "Only upload files up to {0}MB!", + "maxNumber": "Only upload up to {0} files", + "legend": "Legend", + "fileName": "File name", + "fileSize": "File size", + "fileStatue": "File status", + "pending": "Pendig", + "startUpload": "Start upload", + "uploadSuccess": "Upload successfully", + "uploadError": "Upload failed", + "uploading": "Uploading", + "uploadWait": "Please wait for the file upload to finish", + "reUploadFailed": "Re-upload failed files" + }, + "verify": { + "error": "verification failed!", + "time": "The verification is successful and it takes {time} seconds!", + "redoTip": "Click the picture to refresh", + "dragText": "Hold down the slider and drag", + "successText": "Verified" + } +} diff --git a/src/locales/lang/en/layout.json b/src/locales/lang/en/layout.json new file mode 100644 index 0000000..b9acaa1 --- /dev/null +++ b/src/locales/lang/en/layout.json @@ -0,0 +1,96 @@ +{ + "footer": { + "onlinePreview": "Preview", + "onlineDocument": "Document" + }, + "header": { + "dropdownChangeApi": "Change Api", + "dropdownItemDoc": "Document", + "dropdownItemLoginOut": "Switched Systems", + "tooltipErrorLog": "Error log", + "tooltipLock": "Lock screen", + "tooltipNotify": "Notification", + "tooltipEntryFull": "Full Screen", + "tooltipExitFull": "Exit Full Screen", + "lockScreenPassword": "Lock screen password", + "lockScreen": "Lock screen", + "lockScreenBtn": "Locking", + "home": "Home" + }, + "multipleTab": { + "reload": "Refresh current", + "close": "Close current", + "closeLeft": "Close Left", + "closeRight": "Close Right", + "closeOther": "Close Other", + "closeAll": "Close All" + }, + "setting": { + "contentModeFull": "Full", + "contentModeFixed": "Fixed width", + "topMenuAlignLeft": "Left", + "topMenuAlignRight": "Center", + "topMenuAlignCenter": "Right", + "menuTriggerNone": "Not Show", + "menuTriggerBottom": "Bottom", + "menuTriggerTop": "Top", + "menuTypeSidebar": "Left menu mode", + "menuTypeMixSidebar": "Left menu mixed mode", + "menuTypeMix": "Top Menu Mix mode", + "menuTypeTopMenu": "Top menu mode", + "on": "On", + "off": "Off", + "minute": "Minute", + "operatingTitle": "Successful!", + "operatingContent": "The copy is successful, please go to src/settings/projectSetting.ts to modify the configuration!", + "resetSuccess": "Successfully reset!", + "copyBtn": "Copy", + "clearBtn": "Clear cache and to the login page", + "drawerTitle": "Configuration", + "darkMode": "Dark mode", + "navMode": "Navigation mode", + "interfaceFunction": "Interface function", + "interfaceDisplay": "Interface display", + "animation": "Animation", + "splitMenu": "Split menu", + "closeMixSidebarOnChange": "Switch page to close menu", + "sysTheme": "System theme", + "headerTheme": "Header theme", + "sidebarTheme": "Menu theme", + "menuDrag": "Drag Sidebar", + "menuSearch": "Menu search", + "menuAccordion": "Sidebar accordion", + "menuCollapse": "Collapse menu", + "collapseMenuDisplayName": "Collapse menu display name", + "topMenuLayout": "Top menu layout", + "menuCollapseButton": "Menu collapse button", + "contentMode": "Content area width", + "expandedMenuWidth": "Expanded menu width", + "breadcrumb": "Breadcrumbs", + "breadcrumbIcon": "Breadcrumbs Icon", + "tabs": "Tabs", + "tabDetail": "Tab Detail", + "tabsQuickBtn": "Tabs quick button", + "tabsRedoBtn": "Tabs redo button", + "tabsFoldBtn": "Tabs flod button", + "sidebar": "Sidebar", + "header": "Header", + "footer": "Footer", + "fullContent": "Full content", + "grayMode": "Gray mode", + "colorWeak": "Color Weak Mode", + "progress": "Progress", + "switchLoading": "Switch Loading", + "switchAnimation": "Switch animation", + "animationType": "Animation type", + "autoScreenLock": "Auto screen lock", + "notAutoScreenLock": "Not auto lock", + "fixedHeader": "Fixed header", + "fixedSideBar": "Fixed Sidebar", + "mixSidebarTrigger": "Mixed menu Trigger", + "triggerHover": "Hover", + "triggerClick": "Click", + "mixSidebarFixed": "Fixed expanded menu", + "autoCollapseTabsInFold": "Auto collapse tabs in fold" + } +} diff --git a/src/locales/lang/en/routes/basic.json b/src/locales/lang/en/routes/basic.json new file mode 100644 index 0000000..5940171 --- /dev/null +++ b/src/locales/lang/en/routes/basic.json @@ -0,0 +1,4 @@ +{ + "login": "Login", + "errorLogList": "Error Log" +} diff --git a/src/locales/lang/en/routes/dashboard.json b/src/locales/lang/en/routes/dashboard.json new file mode 100644 index 0000000..ad3980c --- /dev/null +++ b/src/locales/lang/en/routes/dashboard.json @@ -0,0 +1,6 @@ +{ + "dashboard": "Dashboard", + "about": "About", + "workbench": "Workbench", + "analysis": "Analysis" +} diff --git a/src/locales/lang/en/routes/demo.json b/src/locales/lang/en/routes/demo.json new file mode 100644 index 0000000..7e71f9e --- /dev/null +++ b/src/locales/lang/en/routes/demo.json @@ -0,0 +1,179 @@ +{ + "charts": { + "baiduMap": "Baidu map", + "aMap": "A map", + "googleMap": "Google map", + "charts": "Chart", + "map": "Map", + "line": "Line", + "pie": "Pie" + }, + "comp": { + "comp": "Component", + "basic": "Basic", + "transition": "Animation", + "countTo": "Count To", + "scroll": "Scroll", + "scrollBasic": "Basic", + "scrollAction": "Scroll Function", + "virtualScroll": "Virtual Scroll", + "tree": "Tree", + "treeBasic": "Basic", + "editTree": "Searchable/toolbar", + "actionTree": "Function operation", + "modal": "Modal", + "drawer": "Drawer", + "desc": "Desc", + "verify": "Verify", + "verifyDrag": "Drag ", + "verifyRotate": "Picture Restore", + "qrcode": "QR code", + "strength": "Password strength", + "upload": "Upload", + "loading": "Loading", + "time": "Relative Time", + "cropperImage": "Cropper Image", + "cardList": "Card List" + }, + "editor": { + "editor": "Editor", + "jsonEditor": "Json editor", + "markdown": "Markdown editor", + "tinymce": "Rich text", + "tinymceBasic": "Basic", + "tinymceForm": "embedded form" + }, + "excel": { + "excel": "Excel", + "customExport": "Select export format", + "jsonExport": "JSON data export", + "arrayExport": "Array data export", + "importExcel": "Import" + }, + "feat": { + "feat": "Page Function", + "icon": "Icon", + "tabs": "Tabs", + "tabDetail": "Tab Detail", + "sessionTimeout": "Session Timeout", + "print": "Print", + "contextMenu": "Context Menu", + "download": "Download", + "clickOutSide": "ClickOutSide", + "imgPreview": "Picture Preview", + "copy": "Clipboard", + "ellipsis": "EllipsisText", + "msg": "Message prompt", + "watermark": "Watermark", + "ripple": "Ripple", + "fullScreen": "Full Screen", + "errorLog": "Error Log", + "tab": "Tab with parameters", + "tab1": "Tab with parameter 1", + "tab2": "Tab with parameter 2", + "menu": "Menu with parameters", + "menu1": "Menu with parameters 1", + "menu2": "Menu with parameters 2", + "ws": "Websocket test", + "breadcrumb": "Breadcrumbs", + "breadcrumbFlat": "Flat Mode", + "breadcrumbFlatDetail": "Flat mode details", + "requestDemo": "Retry request demo", + "breadcrumbChildren": "Level mode", + "breadcrumbChildrenDetail": "Level mode detail" + }, + "flow": { + "name": "Graphics editor", + "flowChart": "FlowChart" + }, + "form": { + "form": "Form", + "basic": "Basic", + "useForm": "useForm", + "refForm": "RefForm", + "advancedForm": "Shrinkable", + "ruleForm": "Form validation", + "dynamicForm": "Dynamic", + "customerForm": "Custom", + "appendForm": "Append", + "tabsForm": "TabsForm" + }, + "iframe": { + "frame": "External", + "antv": "antVue doc (embedded)", + "doc": "Project doc (embedded)", + "docExternal": "Project doc (external)" + }, + "level": { + "level": "MultiMenu" + }, + "page": { + "page": "Page", + "form": "Form", + "formBasic": "Basic Form", + "formStep": "Step Form", + "formHigh": "Advanced Form", + "desc": "Details", + "descBasic": "Basic Details", + "descHigh": "Advanced Details", + "result": "Result", + "resultSuccess": "Success", + "resultFail": "Failed", + "account": "Personal", + "accountCenter": "Personal Center", + "accountSetting": "Personal Settings", + "exception": "Exception", + "netWorkError": "Network Error", + "notData": "No data", + "list": "List page", + "listCard": "Card list", + "basic": "Basic list", + "listBasic": "Basic list", + "listSearch": "Search list" + }, + "permission": { + "permission": "Permission", + "front": "front-end", + "frontPage": "Page", + "frontBtn": "Button", + "frontTestA": "Test page A", + "frontTestB": "Test page B", + "back": "background", + "backPage": "Page", + "backBtn": "Button" + }, + "steps": { + "page": "Intro page" + }, + "system": { + "moduleName": "System management", + "account": "Account management", + "vxeTableAccount": "Account management(VxeTable)", + "account_detail": "Account detail", + "password": "Change password", + "dept": "Department management", + "menu": "Menu management", + "role": "Role management" + }, + "table": { + "table": "Table", + "basic": "Basic", + "treeTable": "Tree", + "fetchTable": "Remote loading", + "fixedColumn": "Fixed column", + "customerCell": "Custom column", + "formTable": "Open search", + "useTable": "UseTable", + "refTable": "RefTable", + "multipleHeader": "MultiLevel header", + "mergeHeader": "Merge cells", + "expandTable": "Expandable table", + "fixedHeight": "Fixed height", + "footerTable": "Footer", + "editCellTable": "Editable cell", + "editRowTable": "Editable row", + "authColumn": "Auth column", + "resizeParentHeightTable": "resizeParentHeightTable", + "vxeTable": "VxeTable" + } +} diff --git a/src/locales/lang/en/sys.json b/src/locales/lang/en/sys.json new file mode 100644 index 0000000..1c29df7 --- /dev/null +++ b/src/locales/lang/en/sys.json @@ -0,0 +1,97 @@ +{ + "api": { + "operationSuccess": "Operation Success", + "operationFailed": "Operation failed", + "errorTip": "Error Tip", + "successTip": "Success Tip", + "errorMessage": "The operation failed, the system is abnormal!", + "timeoutMessage": "Login timed out, please log in again!", + "apiTimeoutMessage": "The interface request timed out, please refresh the page and try again!", + "apiRequestFailed": "The interface request failed, please try again later!", + "networkException": "network anomaly", + "networkExceptionMsg": "Please check if your network connection is normal! The network is abnormal", + "errMsg401": "The user does not have permission (token, user name, password error)!", + "errMsg403": "The user is authorized, but access is forbidden!", + "errMsg404": "Network request error, the resource was not found!", + "errMsg405": "Network request error, request method not allowed!", + "errMsg408": "Network request timed out!", + "errMsg500": "Server error, please contact the administrator!", + "errMsg501": "The network is not implemented!", + "errMsg502": "Network Error!", + "errMsg503": "The service is unavailable, the server is temporarily overloaded or maintained!", + "errMsg504": "Network timeout!", + "errMsg505": "The http version does not support the request!" + }, + "app": { + "logoutTip": "Reminder", + "logoutMessage": "Confirm to exit the system?", + "menuLoading": "Menu loading..." + }, + "navigation": { + "logoutTip": "Reminder", + "logoutMessage": "Confirm return to navigation page?", + "menuLoading": "Menu loading..." + }, + "errorLog": { + "tableTitle": "Error log list", + "tableColumnType": "Type", + "tableColumnDate": "Time", + "tableColumnFile": "File", + "tableColumnMsg": "Error message", + "tableColumnStackMsg": "Stack info", + "tableActionDesc": "Details", + "modalTitle": "Error details", + "fireVueError": "Fire vue error", + "fireResourceError": "Fire resource error", + "fireAjaxError": "Fire ajax error", + "enableMessage": "Only effective when useErrorHandle=true in `/src/settings/projectSetting.ts`." + }, + "exception": { + "backLogin": "Back Login", + "backHome": "Back Home", + "subTitle403": "Sorry, you don't have access to this page.", + "subTitle404": "The current account does not have permission.", + "subTitle500": "Sorry, the server is reporting an error.", + "noDataTitle": "No data on the current page.", + "networkErrorTitle": "Network Error", + "networkErrorSubTitle": "Sorry,Your network connection has been disconnected, please check your network!" + }, + "lock": { + "unlock": "Click to unlock", + "alert": "Lock screen password error", + "backToLogin": "Back to login", + "entry": "Enter the system", + "placeholder": "Please enter the lock screen password or user password" + }, + "login": { + "backSignIn": "Back sign in", + "mobileSignInFormTitle": "Mobile sign in", + "qrSignInFormTitle": "Qr code sign in", + "signInFormTitle": "Sign in", + "signUpFormTitle": "Sign up", + "forgetFormTitle": "Reset password", + "signInTitle": "Integration Of Financial Resources", + "signInDesc": "Enter your personal details and get started!", + "policy": "I agree to the xxx Privacy Policy", + "scanSign": "scanning the code to complete the login", + "loginButton": "Sign in", + "registerButton": "Sign up", + "rememberMe": "Remember me", + "forgetPassword": "Forget Password?", + "otherSignIn": "Sign in with", + "loginSuccessTitle": "Login successful", + "loginSuccessDesc": "Welcome back", + "accountPlaceholder": "Please input username", + "passwordPlaceholder": "Please input password", + "smsPlaceholder": "Please input sms code", + "mobilePlaceholder": "Please input mobile", + "policyPlaceholder": "Register after checking", + "diffPwd": "The two passwords are inconsistent", + "userName": "Username", + "password": "Password", + "confirmPassword": "Confirm Password", + "email": "Email", + "smsCode": "SMS code", + "mobile": "Mobile" + } +} diff --git a/src/locales/lang/zh-CN/antdLocale/DatePicker.json b/src/locales/lang/zh-CN/antdLocale/DatePicker.json new file mode 100644 index 0000000..d4abbde --- /dev/null +++ b/src/locales/lang/zh-CN/antdLocale/DatePicker.json @@ -0,0 +1,19 @@ +{ + "lang": { + "shortWeekDays": ["日", "一", "二", "三", "四", "五", "六"], + "shortMonths": [ + "1月", + "2月", + "3月", + "4月", + "5月", + "6月", + "7月", + "8月", + "9月", + "10月", + "11月", + "12月" + ] + } +} diff --git a/src/locales/lang/zh-CN/common.json b/src/locales/lang/zh-CN/common.json new file mode 100644 index 0000000..19647c8 --- /dev/null +++ b/src/locales/lang/zh-CN/common.json @@ -0,0 +1,20 @@ +{ + "okText": "确认", + "closeText": "关闭", + "cancelText": "取消", + "loadingText": "加载中...", + "saveText": "保存", + "delText": "删除", + "resetText": "重置", + "searchText": "搜索", + "queryText": "查询", + + "inputText": "请输入", + "chooseText": "请选择", + + "redo": "刷新", + "back": "返回", + + "light": "亮色主题", + "dark": "黑暗主题" +} diff --git a/src/locales/lang/zh-CN/component.json b/src/locales/lang/zh-CN/component.json new file mode 100644 index 0000000..8805039 --- /dev/null +++ b/src/locales/lang/zh-CN/component.json @@ -0,0 +1,132 @@ +{ + "app": { + "searchNotData": "暂无搜索结果", + "toSearch": "确认", + "toNavigate": "切换" + }, + "countdown": { + "normalText": "获取验证码", + "sendText": "{0}秒后重新获取" + }, + "cropper": { + "selectImage": "选择图片", + "uploadSuccess": "上传成功", + "imageTooBig": "图片超限", + "modalTitle": "头像上传", + "okText": "确认并上传", + "btn_reset": "重置", + "btn_rotate_left": "逆时针旋转", + "btn_rotate_right": "顺时针旋转", + "btn_scale_x": "水平翻转", + "btn_scale_y": "垂直翻转", + "btn_zoom_in": "放大", + "btn_zoom_out": "缩小", + "preview": "预览" + }, + "drawer": { + "loadingText": "加载中...", + "cancelText": "关闭", + "okText": "确认" + }, + "excel": { + "exportModalTitle": "导出数据", + "fileType": "文件类型", + "fileName": "文件名" + }, + "form": { + "putAway": "收起", + "unfold": "展开", + "maxTip": "字符数应小于{0}位", + "apiSelectNotFound": "请等待数据加载完成..." + }, + "icon": { + "placeholder": "点击选择图标", + "search": "搜索图标", + "copy": "复制图标成功!" + }, + "menu": { + "search": "菜单搜索" + }, + "modal": { + "cancelText": "关闭", + "okText": "确认", + "close": "关闭", + "maximize": "最大化", + "restore": "还原" + }, + "table": { + "settingDens": "密度", + "settingDensDefault": "默认", + "settingDensMiddle": "中等", + "settingDensSmall": "紧凑", + "settingColumn": "列设置", + "settingColumnShow": "列展示", + "settingIndexColumnShow": "序号列", + "settingSelectColumnShow": "勾选列", + "settingFixedLeft": "固定到左侧", + "settingFixedRight": "固定到右侧", + "settingFullScreen": "全屏", + "index": "序号", + "total": "共 {total} 条数据", + "selectionBarTips": "已选择{count}条记录", + "selectionBarClear": "清空", + "selectionBarEmpty": "未选中任何记录" + }, + "time": { + "before": "前", + "after": "后", + "just": "刚刚", + "seconds": "秒", + "minutes": "分钟", + "hours": "小时", + "days": "天" + }, + "tree": { + "selectAll": "选择全部", + "unSelectAll": "取消选择", + "expandAll": "展开全部", + "unExpandAll": "折叠全部", + "checkStrictly": "层级关联", + "checkUnStrictly": "层级独立" + }, + "upload": { + "save": "保存", + "upload": "上传", + "imgUpload": "图片上传", + "uploaded": "已上传", + "operating": "操作", + "del": "删除", + "download": "下载", + "saveWarn": "请等待文件上传后,保存!", + "saveError": "没有上传成功的文件,无法保存!", + "preview": "预览", + "choose": "选择文件", + "accept": "支持{0}格式", + "acceptUpload": "只能上传{0}格式文件", + "maxSize": "单个文件不超过{0}MB", + "maxSizeMultiple": "只能上传不超过{0}MB的文件!", + "maxNumber": "最多只能上传{0}个文件", + "legend": "略缩图", + "fileName": "文件名", + "fileSize": "文件大小", + "fileStatue": "状态", + "pending": "待上传", + "startUpload": "开始上传", + "uploadSuccess": "上传成功", + "uploadError": "上传失败", + "uploading": "上传中", + "uploadWait": "请等待文件上传结束后操作", + "reUploadFailed": "重新上传失败文件" + }, + "verify": { + "error": "验证失败!", + "time": "验证校验成功,耗时{time}秒!", + "redoTip": "点击图片可刷新", + "dragText": "请按住滑块拖动", + "successText": "验证通过" + }, + "map":{ + "refreshSuccess":"获取位置成功!", + "refreshError":"获取位置失败!" + } +} diff --git a/src/locales/lang/zh-CN/layout.json b/src/locales/lang/zh-CN/layout.json new file mode 100644 index 0000000..9fe9b91 --- /dev/null +++ b/src/locales/lang/zh-CN/layout.json @@ -0,0 +1,97 @@ +{ + "footer": { + "onlinePreview": "在线预览", + "onlineDocument": "在线文档" + }, + "header": { + "dropdownChangeApi": "切换API", + "dropdownItemDoc": "文档", + "dropdownItemLoginOut": "退出登录", + "tooltipErrorLog": "错误日志", + "tooltipLock": "锁定屏幕", + "tooltipNotify": "消息通知", + "tooltipEntryFull": "全屏", + "tooltipExitFull": "退出全屏", + "lockScreenPassword": "锁屏密码", + "lockScreen": "锁定屏幕", + "lockScreenBtn": "锁定", + "home": "首页", + "cloud": "云查询进度" + }, + "multipleTab": { + "reload": "重新加载", + "close": "关闭标签页", + "closeLeft": "关闭左侧标签页", + "closeRight": "关闭右侧标签页", + "closeOther": "关闭其它标签页", + "closeAll": "关闭全部标签页" + }, + "setting": { + "contentModeFull": "流式", + "contentModeFixed": "定宽", + "topMenuAlignLeft": "居左", + "topMenuAlignRight": "居中", + "topMenuAlignCenter": "居右", + "menuTriggerNone": "不显示", + "menuTriggerBottom": "底部", + "menuTriggerTop": "顶部", + "menuTypeSidebar": "左侧菜单模式", + "menuTypeMixSidebar": "左侧菜单混合模式", + "menuTypeMix": "顶部菜单混合模式", + "menuTypeTopMenu": "顶部菜单模式", + "on": "开", + "off": "关", + "minute": "分钟", + "operatingTitle": "操作成功", + "operatingContent": "复制成功,请到 src/settings/projectSetting.ts 中修改配置!", + "resetSuccess": "重置成功!", + "copyBtn": "拷贝", + "clearBtn": "清空缓存并返回登录页", + "drawerTitle": "项目配置", + "darkMode": "主题", + "navMode": "导航栏模式", + "interfaceFunction": "界面功能", + "interfaceDisplay": "界面显示", + "animation": "动画", + "splitMenu": "分割菜单", + "closeMixSidebarOnChange": "切换页面关闭菜单", + "sysTheme": "系统主题", + "headerTheme": "顶栏主题", + "sidebarTheme": "菜单主题", + "menuDrag": "侧边菜单拖拽", + "menuSearch": "菜单搜索", + "menuAccordion": "侧边菜单手风琴模式", + "menuCollapse": "折叠菜单", + "collapseMenuDisplayName": "折叠菜单显示名称", + "topMenuLayout": "顶部菜单布局", + "menuCollapseButton": "菜单折叠按钮", + "contentMode": "内容区域宽度", + "expandedMenuWidth": "菜单展开宽度", + "breadcrumb": "面包屑", + "breadcrumbIcon": "面包屑图标", + "tabs": "标签页", + "tabDetail": "标签详情页", + "tabsQuickBtn": "标签页快捷按钮", + "tabsRedoBtn": "标签页刷新按钮", + "tabsFoldBtn": "标签页折叠按钮", + "sidebar": "左侧菜单", + "header": "顶栏", + "footer": "页脚", + "fullContent": "全屏内容", + "grayMode": "灰色模式", + "colorWeak": "色弱模式", + "progress": "顶部进度条", + "switchLoading": "切换loading", + "switchAnimation": "切换动画", + "animationType": "动画类型", + "autoScreenLock": "自动锁屏", + "notAutoScreenLock": "不自动锁屏", + "fixedHeader": "固定header", + "fixedSideBar": "固定Sidebar", + "mixSidebarTrigger": "混合菜单触发方式", + "triggerHover": "悬停", + "triggerClick": "点击", + "mixSidebarFixed": "固定展开菜单", + "autoCollapseTabsInFold": "fold模式下自动收起标签页" + } +} diff --git a/src/locales/lang/zh-CN/routes/basic.json b/src/locales/lang/zh-CN/routes/basic.json new file mode 100644 index 0000000..830ff12 --- /dev/null +++ b/src/locales/lang/zh-CN/routes/basic.json @@ -0,0 +1,4 @@ +{ + "login": "登录", + "errorLogList": "错误日志列表" +} diff --git a/src/locales/lang/zh-CN/routes/dashboard.json b/src/locales/lang/zh-CN/routes/dashboard.json new file mode 100644 index 0000000..d36e4b0 --- /dev/null +++ b/src/locales/lang/zh-CN/routes/dashboard.json @@ -0,0 +1,7 @@ +{ + "dashboard": "Dashboard", + "about": "关于", + "workbench": "工作台", + "analysis": "农源查询", + "test": "Test" +} diff --git a/src/locales/lang/zh-CN/routes/demo.json b/src/locales/lang/zh-CN/routes/demo.json new file mode 100644 index 0000000..f96ebcd --- /dev/null +++ b/src/locales/lang/zh-CN/routes/demo.json @@ -0,0 +1,186 @@ +{ + "charts": { + "baiduMap": "百度地图", + "aMap": "高德地图", + "googleMap": "谷歌地图", + "charts": "图表", + "map": "地图", + "line": "折线图", + "pie": "饼图", + "mars3d":"mars3d" + }, + "comp": { + "comp": "组件", + "basic": "基础组件", + "transition": "动画组件", + "countTo": "数字动画", + "scroll": "滚动组件", + "scrollBasic": "基础滚动", + "scrollAction": "滚动函数", + "virtualScroll": "虚拟滚动", + "tree": "Tree", + "treeBasic": "基础树", + "editTree": "可搜索/工具栏", + "actionTree": "函数操作示例", + "modal": "弹窗扩展", + "drawer": "抽屉扩展", + "desc": "详情组件", + "verify": "验证组件", + "verifyDrag": "拖拽校验", + "verifyRotate": "图片还原", + "qrcode": "二维码组件", + "strength": "密码强度组件", + "upload": "上传组件", + "loading": "Loading", + "time": "相对时间", + "cropperImage": "图片裁剪", + "cardList": "卡片列表" + }, + "editor": { + "editor": "编辑器", + "jsonEditor": "Json编辑器", + "markdown": "markdown编辑器", + "tinymce": "富文本", + "tinymceBasic": "基础使用", + "tinymceForm": "嵌入form" + }, + "excel": { + "excel": "Excel", + "customExport": "选择导出格式", + "jsonExport": "JSON数据导出", + "arrayExport": "Array数据导出", + "importExcel": "导入" + }, + "feat": { + "feat": "功能", + "icon": "图标", + "sessionTimeout": "登录过期", + "tabs": "标签页操作", + "tabDetail": "标签详情页", + "print": "打印", + "contextMenu": "右键菜单", + "download": "文件下载", + "clickOutSide": "ClickOutSide组件", + "imgPreview": "图片预览", + "copy": "剪切板", + "ellipsis": "文本省略", + "msg": "消息提示", + "watermark": "水印", + "ripple": "水波纹", + "fullScreen": "全屏", + "errorLog": "错误日志", + "tab": "Tab带参", + "tab1": "Tab带参1", + "tab2": "Tab带参2", + "menu": "Menu带参", + "menu1": "Menu带参1", + "menu2": "Menu带参2", + "ws": "websocket测试", + "breadcrumb": "面包屑导航", + "breadcrumbFlat": "平级模式", + "requestDemo": "测试请求重试", + "breadcrumbFlatDetail": "平级详情", + "breadcrumbChildren": "层级模式", + "breadcrumbChildrenDetail": "层级详情" + }, + "flow": { + "name": "图形编辑器", + "flowChart": "流程图" + }, + "form": { + "form": "Form", + "basic": "基础表单", + "useForm": "useForm", + "refForm": "RefForm", + "advancedForm": "可收缩表单", + "ruleForm": "表单验证", + "dynamicForm": "动态表单", + "customerForm": "自定义组件", + "appendForm": "表单增删示例", + "tabsForm": "标签页+多级field" + }, + "iframe": { + "frame": "外部页面", + "antv": "antVue文档(内嵌)", + "doc": "项目文档(内嵌)", + "docExternal": "项目文档(外链)" + }, + "level": { + "level": "多级菜单" + }, + "page": { + "page": "页面", + "form": "表单页", + "formBasic": "基础表单", + "formStep": "分步表单", + "formHigh": "高级表单", + "desc": "详情页", + "descBasic": "基础详情页", + "descHigh": "高级详情页", + "result": "结果页", + "resultSuccess": "成功页", + "resultFail": "失败页", + "account": "个人页", + "accountCenter": "个人中心", + "accountSetting": "个人设置", + "exception": "异常页", + "netWorkError": "网络错误", + "notData": "无数据", + "list": "列表页", + "listCard": "卡片列表", + "listBasic": "标准列表", + "listSearch": "搜索列表" + }, + "permission": { + "permission": "权限管理", + "front": "基于前端权限", + "frontPage": "页面权限", + "frontBtn": "按钮权限", + "frontTestA": "权限测试页A", + "frontTestB": "权限测试页B", + "back": "基于后台权限", + "backPage": "页面权限", + "backBtn": "按钮权限" + }, + "steps": { + "page": "引导页" + }, + "system": { + "moduleName": "系统管理", + "account": "账号管理", + "vxeTableAccount": "账号管理(VxeTable)", + "account_detail": "账号详情", + "password": "修改密码", + "dept": "部门管理", + "menu": "菜单管理", + "role": "角色管理", + "position":"职级管理" + }, + "table": { + "table": "Table", + "basic": "基础表格", + "treeTable": "树形表格", + "fetchTable": "远程加载示例", + "fixedColumn": "固定列", + "customerCell": "自定义列", + "formTable": "开启搜索区域", + "useTable": "UseTable", + "refTable": "RefTable", + "multipleHeader": "多级表头", + "mergeHeader": "合并单元格", + "expandTable": "可展开表格", + "fixedHeight": "定高/头部自定义", + "footerTable": "表尾行合计", + "editCellTable": "可编辑单元格", + "editRowTable": "可编辑行", + "authColumn": "权限列", + "resizeParentHeightTable": "继承父元素高度", + "vxeTable": "VxeTable" + }, + "workflow":{ + "scheme_preview":"流程模板设计", + "create_preview":"流程发起", + "task_audit_preview":"审核节点", + "task_look_preview":"查看流程" + } +} diff --git a/src/locales/lang/zh-CN/sys.json b/src/locales/lang/zh-CN/sys.json new file mode 100644 index 0000000..2ff2f9b --- /dev/null +++ b/src/locales/lang/zh-CN/sys.json @@ -0,0 +1,106 @@ +{ + "api": { + "operationSuccess": "操作成功", + "operationFailed": "操作失败", + "errorTip": "错误提示", + "successTip": "成功提示", + "errorMessage": "操作失败,系统异常!", + "timeoutMessage": "登录超时,请重新登录!", + "apiTimeoutMessage": "接口请求超时,请刷新页面重试!", + "apiRequestFailed": "请求出错,请稍候重试", + "networkException": "网络异常", + "networkExceptionMsg": "网络异常,请检查您的网络连接是否正常!", + "errMsg401": "用户没有权限(令牌、用户名、密码错误)!", + "errMsg403": "用户得到授权,但是访问是被禁止的。!", + "errMsg404": "网络请求错误,未找到该资源!", + "errMsg405": "网络请求错误,请求方法未允许!", + "errMsg408": "网络请求超时!", + "errMsg500": "服务器错误,请联系管理员!", + "errMsg501": "网络未实现!", + "errMsg502": "网络错误!", + "errMsg503": "服务不可用,服务器暂时过载或维护!", + "errMsg504": "网络超时!", + "errMsg505": "http版本不支持该请求!" + }, + "app": { + "logoutTip": "温馨提醒", + "logoutMessage": "是否确认退出系统?", + "menuLoading": "菜单加载中..." + }, + "navigation": { + "logoutTip": "温馨提醒", + "logoutMessage": "是否确认回到导航页?", + "menuLoading": "菜单加载中..." + }, + "errorLog": { + "tableTitle": "错误日志列表", + "tableColumnType": "类型", + "tableColumnDate": "时间", + "tableColumnFile": "文件", + "tableColumnMsg": "错误信息", + "tableColumnStackMsg": "stack信息", + "tableActionDesc": "详情", + "modalTitle": "错误详情", + "fireVueError": "点击触发vue错误", + "fireResourceError": "点击触发资源加载错误", + "fireAjaxError": "点击触发ajax错误", + "enableMessage": "只在`/src/settings/projectSetting.ts` 内的useErrorHandle=true时生效." + }, + "exception": { + "backLogin": "返回登录", + "backHome": "返回首页", + "subTitle403": "抱歉,您无权访问此页面。", + "subTitle404": "当前账号无权限访问", + "subTitle500": "抱歉,服务器报告错误。", + "noDataTitle": "当前页无数据", + "networkErrorTitle": "网络错误", + "networkErrorSubTitle": "抱歉,您的网络连接已断开,请检查您的网络!" + }, + "lock": { + "unlock": "点击解锁", + "alert": "锁屏密码错误", + "backToLogin": "返回登录", + "entry": "进入系统", + "placeholder": "请输入锁屏密码或者用户密码" + }, + "login": { + "backSignIn": "返回", + "signInFormTitle": "登录", + "mobileSignInFormTitle": "手机登录", + "qrSignInFormTitle": "二维码登录", + "signUpFormTitle": "注册", + "forgetFormTitle": "重置密码", + "signInTitle": "基础框架", + "signInDesc": "", + "policy": "我同意xxx隐私政策", + "scanSign": "扫码后点击\"确认\",即可完成登录", + "loginButton": "登录", + "registerButton": "注册", + "rememberMe": "记住我", + "forgetPassword": "忘记密码?", + "otherSignIn": "其他登录方式", + "loginSuccessTitle": "登录成功", + "loginSuccessDesc": "欢迎回来", + "accountPlaceholder": "请输入账号", + "passwordPlaceholder": "请输入密码", + "smsPlaceholder": "请输入验证码", + "mobilePlaceholder": "请输入手机号码", + "policyPlaceholder": "勾选后才能注册", + "diffPwd": "两次输入密码不一致", + "userName": "账号", + "password": "密码", + "confirmPassword": "确认密码", + "email": "邮箱", + "smsCode": "短信验证码", + "mobile": "手机号码" + }, + "subject": { + "header_title": "临沂市自然资源综合监管平台", + "header_admin": ",欢迎进入!", + "header_logout": "退出系统", + "bottom_copyright": "管理单位:临沂市自然资源和规划局", + "bottom_copyright_lindidiaocha": "版权所有:临沂市自然资源和规划局", + "bottom_support": "技术⽀持:山东慧创信息科技有限公司", + "bottom_version": "系统版本:V1.0" + } +} diff --git a/src/locales/lang/zh_CN.ts b/src/locales/lang/zh_CN.ts new file mode 100644 index 0000000..7d17d7c --- /dev/null +++ b/src/locales/lang/zh_CN.ts @@ -0,0 +1,18 @@ +import { genMessage } from '../helper'; +import antdLocale from 'ant-design-vue/es/locale/zh_CN'; +import { deepMerge } from '@/utils'; + +const modules = import.meta.glob('./zh-CN/**/*.json', { eager: true }); + +export default { + message: { + ...genMessage(modules as Recordable, 'zh-CN'), + antdLocale: { + ...antdLocale, + DatePicker: deepMerge( + antdLocale.DatePicker, + genMessage(modules as Recordable, 'zh-CN').antdLocale.DatePicker, + ), + }, + }, +}; diff --git a/src/locales/setupI18n.ts b/src/locales/setupI18n.ts new file mode 100644 index 0000000..80f9c6c --- /dev/null +++ b/src/locales/setupI18n.ts @@ -0,0 +1,44 @@ +import type { App } from 'vue'; +import type { I18nOptions } from 'vue-i18n'; + +import { createI18n } from 'vue-i18n'; +import { setHtmlPageLang, setLoadLocalePool } from './helper'; +import { localeSetting } from '@/settings/localeSetting'; +import { useLocaleStoreWithOut } from '@/store/modules/locale'; + +const { fallback, availableLocales } = localeSetting; + +export let i18n: ReturnType; + +async function createI18nOptions(): Promise { + const localeStore = useLocaleStoreWithOut(); + const locale = localeStore.getLocale; + const defaultLocal = await import(`./lang/${locale}.ts`); + const message = defaultLocal.default?.message ?? {}; + + setHtmlPageLang(locale); + setLoadLocalePool((loadLocalePool) => { + loadLocalePool.push(locale); + }); + + return { + legacy: false, + locale, + fallbackLocale: fallback, + messages: { + [locale]: message, + }, + availableLocales: availableLocales, + sync: true, //If you don’t want to inherit locale from global scope, you need to set sync of i18n component option to false. + silentTranslationWarn: true, // true - warning off + missingWarn: false, + silentFallbackWarn: true, + }; +} + +// setup i18n instance with glob +export async function setupI18n(app: App) { + const options = await createI18nOptions(); + i18n = createI18n(options); + app.use(i18n); +} diff --git a/src/locales/useLocale.ts b/src/locales/useLocale.ts new file mode 100644 index 0000000..2f2b677 --- /dev/null +++ b/src/locales/useLocale.ts @@ -0,0 +1,71 @@ +/** + * Multi-language related operations + */ +import type { LocaleType } from '#/config'; + +import { i18n } from './setupI18n'; +import { useLocaleStoreWithOut } from '@/store/modules/locale'; +import { unref, computed } from 'vue'; +import { loadLocalePool, setHtmlPageLang } from './helper'; +import { Locale } from 'ant-design-vue/es/locale'; + +interface LangModule { + message: Recordable; + dateLocale: Recordable; + dateLocaleName: string; +} + +function setI18nLanguage(locale: LocaleType) { + const localeStore = useLocaleStoreWithOut(); + + if (i18n.mode === 'legacy') { + i18n.global.locale = locale; + } else { + (i18n.global.locale as any).value = locale; + } + localeStore.setLocaleInfo({ locale }); + setHtmlPageLang(locale); +} + +export function useLocale() { + const localeStore = useLocaleStoreWithOut(); + const getLocale = computed(() => localeStore.getLocale); + const getShowLocalePicker = computed(() => localeStore.getShowPicker); + + const getAntdLocale = computed((): any => { + const localeMessage = i18n.global.getLocaleMessage<{ antdLocale: Locale }>(unref(getLocale)); + return localeMessage?.antdLocale ?? {}; + }); + + // Switching the language will change the locale of useI18n + // And submit to configuration modification + async function changeLocale(locale: LocaleType) { + const globalI18n = i18n.global; + const currentLocale = unref(globalI18n.locale); + if (currentLocale === locale) { + return locale; + } + + if (loadLocalePool.includes(locale)) { + setI18nLanguage(locale); + return locale; + } + const langModule = ((await import(`./lang/${locale}.ts`)) as any).default as LangModule; + if (!langModule) return; + + const { message } = langModule; + + globalI18n.setLocaleMessage(locale, message); + loadLocalePool.push(locale); + + setI18nLanguage(locale); + return locale; + } + + return { + getLocale, + getShowLocalePicker, + changeLocale, + getAntdLocale, + }; +} diff --git a/src/logics/error-handle/index.ts b/src/logics/error-handle/index.ts new file mode 100644 index 0000000..8705528 --- /dev/null +++ b/src/logics/error-handle/index.ts @@ -0,0 +1,183 @@ +/** + * Used to configure the global error handling function, which can monitor vue errors, script errors, static resource errors and Promise errors + */ + +import type { ErrorLogInfo } from '#/store'; + +import { useErrorLogStoreWithOut } from '@/store/modules/errorLog'; + +import { ErrorTypeEnum } from '@/enums/exceptionEnum'; +import { App } from 'vue'; +import projectSetting from '@/settings/projectSetting'; + +/** + * Handling error stack information + * @param error + */ +function processStackMsg(error: Error) { + if (!error.stack) { + return ''; + } + let stack = error.stack + .replace(/\n/gi, '') // Remove line breaks to save the size of the transmitted content + .replace(/\bat\b/gi, '@') // At in chrome, @ in ff + .split('@') // Split information with @ + .slice(0, 9) // The maximum stack length (Error.stackTraceLimit = 10), so only take the first 10 + .map((v) => v.replace(/^\s*|\s*$/g, '')) // Remove extra spaces + .join('~') // Manually add separators for later display + .replace(/\?[^:]+/gi, ''); // Remove redundant parameters of js file links (?x=1 and the like) + const msg = error.toString(); + if (stack.indexOf(msg) < 0) { + stack = msg + '@' + stack; + } + return stack; +} + +/** + * get comp name + * @param vm + */ +function formatComponentName(vm: any) { + if (vm.$root === vm) { + return { + name: 'root', + path: 'root', + }; + } + + const options = vm.$options as any; + if (!options) { + return { + name: 'anonymous', + path: 'anonymous', + }; + } + const name = options.name || options._componentTag; + return { + name: name, + path: options.__file, + }; +} + +/** + * Configure Vue error handling function + */ +function vueErrorHandler(err: unknown, vm: any, info: string) { + const errorLogStore = useErrorLogStoreWithOut(); + const { name, path } = formatComponentName(vm); + errorLogStore.addErrorLogInfo({ + type: ErrorTypeEnum.VUE, + name, + file: path, + message: (err as Error).message, + stack: processStackMsg(err as Error), + detail: info, + url: window.location.href, + }); +} + +/** + * Configure script error handling function + */ +export function scriptErrorHandler( + event: Event | string, + source?: string, + lineno?: number, + colno?: number, + error?: Error, +) { + if (event === 'Script error.' && !source) { + return false; + } + const errorInfo: Partial = {}; + colno = colno || (window.event && (window.event as any).errorCharacter) || 0; + errorInfo.message = event as string; + if (error?.stack) { + errorInfo.stack = error.stack; + } else { + errorInfo.stack = ''; + } + const name = source ? source.substr(source.lastIndexOf('/') + 1) : 'script'; + const errorLogStore = useErrorLogStoreWithOut(); + errorLogStore.addErrorLogInfo({ + type: ErrorTypeEnum.SCRIPT, + name: name, + file: source as string, + detail: 'lineno' + lineno, + url: window.location.href, + ...(errorInfo as Pick), + }); + return true; +} + +/** + * Configure Promise error handling function + */ +function registerPromiseErrorHandler() { + window.addEventListener( + 'unhandledrejection', + function (event) { + const errorLogStore = useErrorLogStoreWithOut(); + errorLogStore.addErrorLogInfo({ + type: ErrorTypeEnum.PROMISE, + name: 'Promise Error!', + file: 'none', + detail: 'promise error!', + url: window.location.href, + stack: 'promise error!', + message: event.reason, + }); + }, + true, + ); +} + +/** + * Configure monitoring resource loading error handling function + */ +function registerResourceErrorHandler() { + // Monitoring resource loading error(img,script,css,and jsonp) + window.addEventListener( + 'error', + function (e: Event) { + const target = e.target ? e.target : (e.srcElement as any); + const errorLogStore = useErrorLogStoreWithOut(); + errorLogStore.addErrorLogInfo({ + type: ErrorTypeEnum.RESOURCE, + name: 'Resource Error!', + file: (e.target || ({} as any)).currentSrc, + detail: JSON.stringify({ + tagName: target.localName, + html: target.outerHTML, + type: e.type, + }), + url: window.location.href, + stack: 'resource is not found', + message: (e.target || ({} as any)).localName + ' is load error', + }); + }, + true, + ); +} + +/** + * Configure global error handling + * @param app + */ +export function setupErrorHandle(app: App) { + const { useErrorHandle } = projectSetting; + if (!useErrorHandle) { + return; + } + // Vue exception monitoring; + app.config.errorHandler = vueErrorHandler; + + // script error + window.onerror = scriptErrorHandler; + + // promise exception + registerPromiseErrorHandler(); + + // Static resource exception + registerResourceErrorHandler(); +} diff --git a/src/logics/initAppConfig.ts b/src/logics/initAppConfig.ts new file mode 100644 index 0000000..364a4cb --- /dev/null +++ b/src/logics/initAppConfig.ts @@ -0,0 +1,77 @@ +/** + * Application configuration + */ +import type { ProjectConfig } from '#/config'; + +import { PROJ_CFG_KEY } from '@/enums/cacheEnum'; +import projectSetting from '@/settings/projectSetting'; + +import { updateDarkTheme } from '@/logics/theme/dark'; +import { updateHeaderBgColor, updateSidebarBgColor } from '@/logics/theme/updateBackground'; +import { updateColorWeak } from '@/logics/theme/updateColorWeak'; +import { updateGrayMode } from '@/logics/theme/updateGrayMode'; + +import { useAppStore } from '@/store/modules/app'; +import { useLocaleStore } from '@/store/modules/locale'; + +import { getCommonStoragePrefix, getStorageShortName } from '@/utils/env'; + +import { ThemeEnum } from '@/enums/appEnum'; +import { deepMerge } from '@/utils'; +import { Persistent } from '@/utils/cache/persistent'; + +// Initial project configuration +export function initAppConfigStore() { + const localeStore = useLocaleStore(); + const appStore = useAppStore(); + let projCfg: ProjectConfig = Persistent.getLocal(PROJ_CFG_KEY) as ProjectConfig; + projCfg = deepMerge(projectSetting, projCfg || {}); + const darkMode = appStore.getDarkMode; + const { + colorWeak, + grayMode, + + headerSetting: { bgColor: headerBgColor } = {}, + menuSetting: { bgColor } = {}, + } = projCfg; + try { + grayMode && updateGrayMode(grayMode); + colorWeak && updateColorWeak(colorWeak); + } catch (error) { + console.log(error); + } + appStore.setProjectConfig(projCfg); + + // init dark mode + updateDarkTheme(darkMode); + if (darkMode === ThemeEnum.DARK) { + updateHeaderBgColor(); + updateSidebarBgColor(); + } else { + headerBgColor && updateHeaderBgColor(headerBgColor); + bgColor && updateSidebarBgColor(bgColor); + } + // init store + localeStore.initLocale(); + + setTimeout(() => { + clearObsoleteStorage(); + }, 16); +} + +/** + * As the version continues to iterate, there will be more and more cache keys stored in localStorage. + * This method is used to delete useless keys + */ +export function clearObsoleteStorage() { + const commonPrefix = getCommonStoragePrefix(); + const shortPrefix = getStorageShortName(); + + [localStorage, sessionStorage].forEach((item: Storage) => { + Object.keys(item).forEach((key) => { + if (key && key.startsWith(commonPrefix) && !key.startsWith(shortPrefix)) { + item.removeItem(key); + } + }); + }); +} diff --git a/src/logics/mitt/routeChange.ts b/src/logics/mitt/routeChange.ts new file mode 100644 index 0000000..e28e309 --- /dev/null +++ b/src/logics/mitt/routeChange.ts @@ -0,0 +1,33 @@ +/** + * Used to monitor routing changes to change the status of menus and tabs. There is no need to monitor the route, because the route status change is affected by the page rendering time, which will be slow + */ + +import { mitt } from '@/utils/mitt'; +import type { RouteLocationNormalized } from 'vue-router'; +import { getRawRoute } from '@/utils'; + +const key = Symbol(); + +const emitter = mitt<{ + [key]: RouteLocationNormalized; +}>(); + +let lastChangeTab: RouteLocationNormalized; + +export function setRouteChange(lastChangeRoute: RouteLocationNormalized) { + const r = getRawRoute(lastChangeRoute); + emitter.emit(key, r); + lastChangeTab = r; +} + +export function listenerRouteChange( + callback: (route: RouteLocationNormalized) => void, + immediate = true, +) { + emitter.on(key, callback); + immediate && lastChangeTab && callback(lastChangeTab); +} + +export function removeTabChangeListener() { + emitter.clear(); +} diff --git a/src/logics/theme/dark.ts b/src/logics/theme/dark.ts new file mode 100644 index 0000000..4d751cf --- /dev/null +++ b/src/logics/theme/dark.ts @@ -0,0 +1,26 @@ +import { addClass, hasClass, removeClass } from '@/utils/domUtils'; + +export type CustomColorType = { + name: string; + light: string; + dark: string; +}; + +export async function updateDarkTheme(mode: string | null = 'light') { + const htmlRoot = document.getElementById('htmlRoot'); + if (!htmlRoot) { + return; + } + const hasDarkClass = hasClass(htmlRoot, 'dark'); + if (mode === 'dark') { + htmlRoot.setAttribute('data-theme', 'dark'); + if (!hasDarkClass) { + addClass(htmlRoot, 'dark'); + } + } else { + htmlRoot.setAttribute('data-theme', 'light'); + if (hasDarkClass) { + removeClass(htmlRoot, 'dark'); + } + } +} diff --git a/src/logics/theme/index.ts b/src/logics/theme/index.ts new file mode 100644 index 0000000..d8e80b7 --- /dev/null +++ b/src/logics/theme/index.ts @@ -0,0 +1 @@ +export async function changeTheme(_color: string) {} diff --git a/src/logics/theme/updateBackground.ts b/src/logics/theme/updateBackground.ts new file mode 100644 index 0000000..3b2d8be --- /dev/null +++ b/src/logics/theme/updateBackground.ts @@ -0,0 +1,76 @@ +import { colorIsDark, lighten, darken } from '@/utils/color'; +import { useAppStore } from '@/store/modules/app'; +import { ThemeEnum } from '@/enums/appEnum'; +import { setCssVar } from './util'; + +const HEADER_BG_COLOR_VAR = '--header-bg-color'; +const HEADER_BG_HOVER_COLOR_VAR = '--header-bg-hover-color'; +const HEADER_MENU_ACTIVE_BG_COLOR_VAR = '--header-active-menu-bg-color'; + +const SIDER_DARK_BG_COLOR = '--sider-dark-bg-color'; +const SIDER_DARK_DARKEN_BG_COLOR = '--sider-dark-darken-bg-color'; +const SIDER_LIGHTEN_BG_COLOR = '--sider-dark-lighten-bg-color'; + +/** + * Change the background color of the top header + * @param color + */ +export function updateHeaderBgColor(color?: string) { + const appStore = useAppStore(); + const darkMode = appStore.getDarkMode === ThemeEnum.DARK; + if (!color) { + if (darkMode) { + color = '#151515'; + } else { + color = appStore.getHeaderSetting.bgColor; + } + } + + // bg color + setCssVar(HEADER_BG_COLOR_VAR, color); + + // hover color + const hoverColor = lighten(color!, 6); + setCssVar(HEADER_BG_HOVER_COLOR_VAR, hoverColor); + setCssVar(HEADER_MENU_ACTIVE_BG_COLOR_VAR, hoverColor); + + // Determine the depth of the color value and automatically switch the theme + const isDark = colorIsDark(color!); + + appStore.setProjectConfig({ + headerSetting: { + theme: isDark || darkMode ? ThemeEnum.DARK : ThemeEnum.LIGHT, + }, + }); +} + +/** + * Change the background color of the left menu + * @param color bg color + */ +export function updateSidebarBgColor(color?: string) { + const appStore = useAppStore(); + + // if (!isHexColor(color)) return; + const darkMode = appStore.getDarkMode === ThemeEnum.DARK; + if (!color) { + if (darkMode) { + color = '#212121'; + } else { + color = appStore.getMenuSetting.bgColor; + } + } + setCssVar(SIDER_DARK_BG_COLOR, color); + setCssVar(SIDER_DARK_DARKEN_BG_COLOR, darken(color!, 6)); + setCssVar(SIDER_LIGHTEN_BG_COLOR, lighten(color!, 5)); + + // only #ffffff is light + // Only when the background color is #fff, the theme of the menu will be changed to light + const isLight = ['#fff', '#ffffff'].includes(color!.toLowerCase()); + + appStore.setProjectConfig({ + menuSetting: { + theme: isLight && !darkMode ? ThemeEnum.LIGHT : ThemeEnum.DARK, + }, + }); +} diff --git a/src/logics/theme/updateColorWeak.ts b/src/logics/theme/updateColorWeak.ts new file mode 100644 index 0000000..8a0e64a --- /dev/null +++ b/src/logics/theme/updateColorWeak.ts @@ -0,0 +1,9 @@ +import { toggleClass } from './util'; + +/** + * Change the status of the project's color weakness mode + * @param colorWeak + */ +export function updateColorWeak(colorWeak: boolean) { + toggleClass(colorWeak, 'color-weak', document.documentElement); +} diff --git a/src/logics/theme/updateGrayMode.ts b/src/logics/theme/updateGrayMode.ts new file mode 100644 index 0000000..0fd16fe --- /dev/null +++ b/src/logics/theme/updateGrayMode.ts @@ -0,0 +1,9 @@ +import { toggleClass } from './util'; + +/** + * Change project gray mode status + * @param gray + */ +export function updateGrayMode(gray: boolean) { + toggleClass(gray, 'gray-mode', document.documentElement); +} diff --git a/src/logics/theme/util.ts b/src/logics/theme/util.ts new file mode 100644 index 0000000..30aef37 --- /dev/null +++ b/src/logics/theme/util.ts @@ -0,0 +1,11 @@ +const docEle = document.documentElement; +export function toggleClass(flag: boolean, clsName: string, target?: HTMLElement) { + const targetEl = target || document.body; + let { className } = targetEl; + className = className.replace(clsName, ''); + targetEl.className = flag ? `${className} ${clsName} ` : className; +} + +export function setCssVar(prop: string, val: any, dom = docEle) { + dom.style.setProperty(prop, val); +} diff --git a/src/main.ts b/src/main.ts new file mode 100644 index 0000000..b2f3b20 --- /dev/null +++ b/src/main.ts @@ -0,0 +1,86 @@ +import 'uno.css'; +import '@/design/index.less'; +import '@/components/VxeTable/src/css/index.scss'; +import 'ant-design-vue/dist/reset.css'; +// Register icon sprite +import 'virtual:svg-icons-register'; + +import { createApp } from 'vue'; + +import { registerGlobComp } from '@/components/registerGlobComp'; +import { setupGlobDirectives } from '@/directives'; +import { setupI18n } from '@/locales/setupI18n'; +import { setupErrorHandle } from '@/logics/error-handle'; +import { initAppConfigStore } from '@/logics/initAppConfig'; +import { router, setupRouter } from '@/router'; +import { setupRouterGuard } from '@/router/guard'; +import { setupStore } from '@/store'; + +import VideoPlayer from 'vue-video-player'; +import 'vue-video-player/src/custom-theme.css'; + +import App from './App.vue'; + +import 'mars3d-cesium/Build/Cesium/Widgets/widgets.css'; +import 'mars3d/mars3d.css'; + +import ElementPlus from 'element-plus'; +import 'element-plus/theme-chalk/index.css'; +import VForm3 from '@/../lib/vform/designer.umd.js'; +import '../lib/vform/designer.style.css'; + +import 'bpmn-js/dist/assets/diagram-js.css'; +import 'bpmn-js/dist/assets/bpmn-font/css/bpmn-embedded.css'; + +import Antd from 'ant-design-vue'; +import { signal } from './utils/signalR'; + +async function bootstrap() { + const app = createApp(App); + app.use(Antd); + + // Configure store + // 配置 store + setupStore(app); + + // Initialize internal system configuration + // 初始化内部系统配置 + initAppConfigStore(); + + // Register global components + // 注册全局组件 + registerGlobComp(app); + + // Multilingual configuration + // 多语言配置 + // Asynchronous case: language files may be obtained from the server side + // 异步案例:语言文件可能从服务器端获取 + await setupI18n(app); + + // Configure routing + // 配置路由 + setupRouter(app); + + // router-guard + // 路由守卫 + setupRouterGuard(router); + + // Register global directive + // 注册全局指令 + setupGlobDirectives(app); + + // Configure global error handling + // 配置全局错误处理 + setupErrorHandle(app); + + // https://next.router.vuejs.org/api/#isready + // await router.isReady(); + + app.use(ElementPlus); + app.use(VForm3); + app.use(VideoPlayer); + app.use(signal); + app.mount('#app'); +} + +bootstrap(); diff --git a/src/router/constant.ts b/src/router/constant.ts new file mode 100644 index 0000000..e57bc26 --- /dev/null +++ b/src/router/constant.ts @@ -0,0 +1,24 @@ +export const REDIRECT_NAME = 'Redirect'; + +export const PARENT_LAYOUT_NAME = 'ParentLayout'; + +export const PAGE_NOT_FOUND_NAME = 'PageNotFound'; + +export const EXCEPTION_COMPONENT = () => import('@/views/sys/exception/Exception.vue'); + +/** + * @description: default layout + */ +export const LAYOUT = () => import('@/layouts/default/index.vue'); + +/** + * @description: parent-layout + */ +export const getParentLayout = (_name?: string) => { + return () => + new Promise((resolve) => { + resolve({ + name: _name || PARENT_LAYOUT_NAME, + }); + }); +}; diff --git a/src/router/guard/index.ts b/src/router/guard/index.ts new file mode 100644 index 0000000..f643cc2 --- /dev/null +++ b/src/router/guard/index.ts @@ -0,0 +1,146 @@ +import type { Router, RouteLocationNormalized } from 'vue-router'; +import { useAppStoreWithOut } from '@/store/modules/app'; +import { useUserStoreWithOut } from '@/store/modules/user'; +import { useTransitionSetting } from '@/hooks/setting/useTransitionSetting'; +import { AxiosCanceler } from '@/utils/http/axios/axiosCancel'; +import { Modal, notification } from 'ant-design-vue'; +import { warn } from '@/utils/log'; +import { unref } from 'vue'; +import { setRouteChange } from '@/logics/mitt/routeChange'; +import { createPermissionGuard } from './permissionGuard'; +import { createStateGuard } from './stateGuard'; +import nProgress from 'nprogress'; +import projectSetting from '@/settings/projectSetting'; +import { createParamMenuGuard } from './paramMenuGuard'; + +// Don't change the order of creation +export function setupRouterGuard(router: Router) { + createPageGuard(router); + createPageLoadingGuard(router); + createHttpGuard(router); + createScrollGuard(router); + createMessageGuard(router); + createProgressGuard(router); + createPermissionGuard(router); + createParamMenuGuard(router); // must after createPermissionGuard (menu has been built.) + createStateGuard(router); +} + +/** + * Hooks for handling page state + */ +function createPageGuard(router: Router) { + const loadedPageMap = new Map(); + + router.beforeEach(async (to) => { + // The page has already been loaded, it will be faster to open it again, you don’t need to do loading and other processing + to.meta.loaded = !!loadedPageMap.get(to.path); + // Notify routing changes + setRouteChange(to); + + return true; + }); + + router.afterEach((to) => { + loadedPageMap.set(to.path, true); + }); +} + +// Used to handle page loading status +function createPageLoadingGuard(router: Router) { + const userStore = useUserStoreWithOut(); + const appStore = useAppStoreWithOut(); + const { getOpenPageLoading } = useTransitionSetting(); + router.beforeEach(async (to) => { + if (!userStore.getToken) { + return true; + } + if (to.meta.loaded) { + return true; + } + + if (unref(getOpenPageLoading)) { + appStore.setPageLoadingAction(true); + return true; + } + + return true; + }); + router.afterEach(async () => { + if (unref(getOpenPageLoading)) { + // TODO Looking for a better way + // The timer simulates the loading time to prevent flashing too fast, + setTimeout(() => { + appStore.setPageLoading(false); + }, 220); + } + return true; + }); +} + +/** + * The interface used to close the current page to complete the request when the route is switched + * @param router + */ +function createHttpGuard(router: Router) { + const { removeAllHttpPending } = projectSetting; + let axiosCanceler: Nullable; + if (removeAllHttpPending) { + axiosCanceler = new AxiosCanceler(); + } + router.beforeEach(async () => { + // Switching the route will delete the previous request + axiosCanceler?.removeAllPending(); + return true; + }); +} + +// Routing switch back to the top +function createScrollGuard(router: Router) { + const isHash = (href: string) => { + return /^#/.test(href); + }; + + router.afterEach(async (to) => { + // scroll top + isHash((to as RouteLocationNormalized & { href: string })?.href) && + document.querySelector('.vben-layout-content')?.scrollTo(0, 0); + return true; + }); +} + +/** + * Used to close the message instance when the route is switched + * @param router + */ +export function createMessageGuard(router: Router) { + const { closeMessageOnSwitch } = projectSetting; + + router.beforeEach(async () => { + try { + if (closeMessageOnSwitch) { + Modal.destroyAll(); + notification.destroy(); + } + } catch (error) { + warn('message guard error:' + error); + } + return true; + }); +} + +export function createProgressGuard(router: Router) { + const { getOpenNProgress } = useTransitionSetting(); + router.beforeEach(async (to) => { + if (to.meta.loaded) { + return true; + } + unref(getOpenNProgress) && nProgress.start(); + return true; + }); + + router.afterEach(async () => { + unref(getOpenNProgress) && nProgress.done(); + return true; + }); +} diff --git a/src/router/guard/paramMenuGuard.ts b/src/router/guard/paramMenuGuard.ts new file mode 100644 index 0000000..886fa21 --- /dev/null +++ b/src/router/guard/paramMenuGuard.ts @@ -0,0 +1,47 @@ +import type { Router } from 'vue-router'; +import { configureDynamicParamsMenu } from '../helper/menuHelper'; +import { Menu } from '../types'; +import { PermissionModeEnum } from '@/enums/appEnum'; +import { useAppStoreWithOut } from '@/store/modules/app'; + +import { usePermissionStoreWithOut } from '@/store/modules/permission'; + +export function createParamMenuGuard(router: Router) { + const permissionStore = usePermissionStoreWithOut(); + router.beforeEach(async (to, _, next) => { + // filter no name route + if (!to.name) { + next(); + return; + } + + // menu has been built. + if (!permissionStore.getIsDynamicAddedRoute) { + next(); + return; + } + + let menus: Menu[] = []; + if (isBackMode()) { + menus = permissionStore.getBackMenuList; + } else if (isRouteMappingMode()) { + menus = permissionStore.getFrontMenuList; + } + menus.forEach((item) => configureDynamicParamsMenu(item, to.params)); + + next(); + }); +} + +const getPermissionMode = () => { + const appStore = useAppStoreWithOut(); + return appStore.getProjectConfig.permissionMode; +}; + +const isBackMode = () => { + return getPermissionMode() === PermissionModeEnum.BACK; +}; + +const isRouteMappingMode = () => { + return getPermissionMode() === PermissionModeEnum.ROUTE_MAPPING; +}; diff --git a/src/router/guard/permissionGuard.ts b/src/router/guard/permissionGuard.ts new file mode 100644 index 0000000..8f1bad3 --- /dev/null +++ b/src/router/guard/permissionGuard.ts @@ -0,0 +1,119 @@ +import type { Router, RouteRecordRaw } from 'vue-router'; + +import { usePermissionStoreWithOut } from '@/store/modules/permission'; + +import { PageEnum } from '@/enums/pageEnum'; +import { useUserStoreWithOut } from '@/store/modules/user'; + +import { PAGE_NOT_FOUND_ROUTE } from '@/router/routes/basic'; + +import { RootRoute } from '@/router/routes'; + +const LOGIN_PATH = PageEnum.BASE_LOGIN; + +const ROOT_PATH = RootRoute.path; + +const whitePathList: PageEnum[] = [LOGIN_PATH]; + +export function createPermissionGuard(router: Router) { + const userStore = useUserStoreWithOut(); + const permissionStore = usePermissionStoreWithOut(); + router.beforeEach(async (to, from, next) => { + if ( + from.path === ROOT_PATH && + to.path === PageEnum.BASE_HOME && + userStore.getUserInfo.homePath && + userStore.getUserInfo.homePath !== PageEnum.BASE_HOME + ) { + next(userStore.getUserInfo.homePath); + return; + } + + const token = userStore.getToken; + + // Whitelist can be directly entered + if (whitePathList.includes(to.path as PageEnum)) { + if (to.path === LOGIN_PATH && token) { + const isSessionTimeout = userStore.getSessionTimeout; + try { + await userStore.afterLoginAction(); + if (!isSessionTimeout) { + next((to.query?.redirect as string) || '/'); + return; + } + } catch { + // + } + } + next(); + return; + } + // token or user does not exist + if (!token) { + // You can access without permission. You need to set the routing meta.ignoreAuth to true + if (to.meta.ignoreAuth) { + next(); + return; + } + + // redirect login page + const redirectData: { path: string; replace: boolean; query?: Recordable } = { + path: LOGIN_PATH, + replace: true, + }; + if (to.path) { + redirectData.query = { + ...redirectData.query, + redirect: to.path, + }; + } + next(redirectData); + return; + } + + // Jump to the 404 page after processing the login + if ( + from.path === LOGIN_PATH && + to.name === PAGE_NOT_FOUND_ROUTE.name && + to.fullPath !== (userStore.getUserInfo.homePath || PageEnum.BASE_HOME) + ) { + next(userStore.getUserInfo.homePath || PageEnum.BASE_HOME); + return; + } + + // get userinfo while last fetch time is empty + if (userStore.getLastUpdateTime === 0) { + try { + await userStore.getUserInfoAction(); + } catch (err) { + next(); + return; + } + } + + if (permissionStore.getIsDynamicAddedRoute) { + next(); + return; + } + + const routes = await permissionStore.buildRoutesAction(); + + routes.forEach((route) => { + router.addRoute(route as unknown as RouteRecordRaw); + }); + + router.addRoute(PAGE_NOT_FOUND_ROUTE as unknown as RouteRecordRaw); + + permissionStore.setDynamicAddedRoute(true); + + if (to.name === PAGE_NOT_FOUND_ROUTE.name) { + // 动态添加路由后,此处应当重定向到fullPath,否则会加载404页面内容 + next({ path: to.fullPath, replace: true, query: to.query }); + } else { + const redirectPath = (from.query.redirect || to.path) as string; + const redirect = decodeURIComponent(redirectPath); + const nextData = to.path === redirect ? { ...to, replace: true } : { path: redirect }; + next(nextData); + } + }); +} diff --git a/src/router/guard/stateGuard.ts b/src/router/guard/stateGuard.ts new file mode 100644 index 0000000..d91b7d2 --- /dev/null +++ b/src/router/guard/stateGuard.ts @@ -0,0 +1,24 @@ +import type { Router } from 'vue-router'; +import { useAppStore } from '@/store/modules/app'; +import { useMultipleTabStore } from '@/store/modules/multipleTab'; +import { useUserStore } from '@/store/modules/user'; +import { usePermissionStore } from '@/store/modules/permission'; +import { PageEnum } from '@/enums/pageEnum'; +import { removeTabChangeListener } from '@/logics/mitt/routeChange'; + +export function createStateGuard(router: Router) { + router.afterEach((to) => { + // Just enter the login page and clear the authentication information + if (to.path === PageEnum.BASE_LOGIN) { + const tabStore = useMultipleTabStore(); + const userStore = useUserStore(); + const appStore = useAppStore(); + const permissionStore = usePermissionStore(); + appStore.resetAllState(); + permissionStore.resetState(); + tabStore.resetState(); + userStore.resetState(); + removeTabChangeListener(); + } + }); +} diff --git a/src/router/helper/menuHelper.ts b/src/router/helper/menuHelper.ts new file mode 100644 index 0000000..3d4fc03 --- /dev/null +++ b/src/router/helper/menuHelper.ts @@ -0,0 +1,110 @@ +import { AppRouteModule } from '@/router/types'; +import type { MenuModule, Menu, AppRouteRecordRaw } from '@/router/types'; +import { findPath, treeMap } from '@/utils/helper/treeHelper'; +import { cloneDeep } from 'lodash-es'; +import { isHttpUrl } from '@/utils/is'; +import { RouteParams } from 'vue-router'; +import { toRaw } from 'vue'; + +export function getAllParentPath(treeData: T[], path: string) { + const menuList = findPath(treeData, (n) => n.path === path) as Menu[]; + return (menuList || []).map((item) => item.path); +} + +// 路径处理 +function joinParentPath(menus: Menu[], parentPath = '') { + for (let index = 0; index < menus.length; index++) { + const menu = menus[index]; + if(menu.meta == undefined){ + return + } + // https://next.router.vuejs.org/guide/essentials/nested-routes.html + // Note that nested paths that start with / will be treated as a root path. + // 请注意,以 / 开头的嵌套路径将被视为根路径。 + // This allows you to leverage the component nesting without having to use a nested URL. + // 这允许你利用组件嵌套,而无需使用嵌套 URL。 + if (!(menu.path.startsWith('/') || isHttpUrl(menu.path))) { + // path doesn't start with /, nor is it a url, join parent path + // 路径不以 / 开头,也不是 url,加入父路径 + menu.path = `${parentPath}/${menu.path}`; + } + if (menu?.children?.length) { + joinParentPath(menu.children, menu.meta?.hidePathForChildren ? parentPath : menu.path); + } + } +} + +// Parsing the menu module +export function transformMenuModule(menuModule: MenuModule): Menu { + const { menu } = menuModule; + + const menuList = [menu]; + + joinParentPath(menuList); + return menuList[0]; +} + +// 将路由转换成菜单 +export function transformRouteToMenu(routeModList: AppRouteModule[], routerMapping = false) { + // 借助 lodash 深拷贝 + const cloneRouteModList = cloneDeep(routeModList); + const routeList: AppRouteRecordRaw[] = []; + + // 对路由项进行修改 + cloneRouteModList.forEach((item) => { + // if (routerMapping && item.meta.hideChildrenInMenu && typeof item.redirect === 'string') { + if (routerMapping && typeof item.redirect === 'string') { + item.path = item.redirect; + } + + if (item.meta?.single) { + const realItem = item?.children?.[0]; + realItem && routeList.push(realItem); + } else { + routeList.push(item); + } + }); + // 提取树指定结构 + const list = treeMap(routeList, { + conversion: (node: AppRouteRecordRaw) => { + const { meta: { title, hideMenu = false } = {} } = node; + + return { + ...(node.meta || {}), + meta: node.meta, + name: title, + hideMenu, + path: node.path, + ...(node.redirect ? { redirect: node.redirect } : {}), + }; + }, + }); + // 路径处理 + joinParentPath(list); + return cloneDeep(list); +} + +/** + * config menu with given params + */ +const menuParamRegex = /(?::)([\s\S]+?)((?=\/)|$)/g; + +export function configureDynamicParamsMenu(menu: Menu, params: RouteParams) { + const { path, paramPath } = toRaw(menu); + let realPath = paramPath ? paramPath : path; + const matchArr = realPath.match(menuParamRegex); + + matchArr?.forEach((it) => { + const realIt = it.substr(1); + if (params[realIt]) { + realPath = realPath.replace(`:${realIt}`, params[realIt] as string); + } + }); + // save original param path. + if (!paramPath && matchArr && matchArr.length > 0) { + menu.paramPath = path; + } + menu.path = realPath; + // children + menu.children?.forEach((item) => configureDynamicParamsMenu(item, params)); +} diff --git a/src/router/helper/routeHelper.ts b/src/router/helper/routeHelper.ts new file mode 100644 index 0000000..7529fa2 --- /dev/null +++ b/src/router/helper/routeHelper.ts @@ -0,0 +1,183 @@ +import type { AppRouteModule, AppRouteRecordRaw } from '@/router/types'; +import type { Router, RouteRecordNormalized } from 'vue-router'; + +import { getParentLayout, LAYOUT, EXCEPTION_COMPONENT } from '@/router/constant'; +import { cloneDeep, omit } from 'lodash-es'; +import { warn } from '@/utils/log'; +import { createRouter, createWebHashHistory } from 'vue-router'; + +export type LayoutMapKey = 'LAYOUT'; +const IFRAME = () => import('@/views/sys/iframe/FrameBlank.vue'); + +const LayoutMap = new Map Promise>(); + +LayoutMap.set('LAYOUT', LAYOUT); +LayoutMap.set('IFRAME', IFRAME); + +let dynamicViewsModules: Record Promise>; + +// Dynamic introduction +function asyncImportRoute(routes: AppRouteRecordRaw[] | undefined) { + dynamicViewsModules = dynamicViewsModules || import.meta.glob('../../views/**/*.{vue,tsx}'); + if (!routes) return; + routes.forEach((item) => { + if (!item.component && item.meta?.frameSrc) { + item.component = 'IFRAME'; + } + const { component, name } = item; + const { children } = item; + if (component) { + const layoutFound = LayoutMap.get(component.toUpperCase()); + if (layoutFound) { + item.component = layoutFound; + } else { + item.component = dynamicImport(dynamicViewsModules, component as string); + } + } else if (name) { + item.component = getParentLayout(); + } + children && asyncImportRoute(children); + }); +} + +function dynamicImport( + dynamicViewsModules: Record Promise>, + component: string, +) { + const keys = Object.keys(dynamicViewsModules); + const matchKeys = keys.filter((key) => { + const k = key.replace('../../views', ''); + const startFlag = component.startsWith('/'); + const endFlag = component.endsWith('.vue') || component.endsWith('.tsx'); + const startIndex = startFlag ? 0 : 1; + const lastIndex = endFlag ? k.length : k.lastIndexOf('.'); + return k.substring(startIndex, lastIndex) === component; + }); + if (matchKeys?.length === 1) { + const matchKey = matchKeys[0]; + return dynamicViewsModules[matchKey]; + } else if (matchKeys?.length > 1) { + warn( + 'Please do not create `.vue` and `.TSX` files with the same file name in the same hierarchical directory under the views folder. This will cause dynamic introduction failure', + ); + return; + } else { + warn('在src/views/下找不到`' + component + '.vue` 或 `' + component + '.tsx`, 请自行创建!'); + return EXCEPTION_COMPONENT; + } +} + +// Turn background objects into routing objects +// 将背景对象变成路由对象 +export function transformObjToRoute(routeList: AppRouteModule[]): T[] { + routeList.forEach((route) => { + const component = route.component as string; + if (component) { + if (component.toUpperCase() === 'LAYOUT') { + route.component = LayoutMap.get(component.toUpperCase()); + } else { + route.children = [cloneDeep(route)]; + route.component = LAYOUT; + + //某些情况下如果name如果没有值, 多个一级路由菜单会导致页面404 + if (!route.name) { + warn('找不到菜单对应的name, 请检查数据!' + JSON.stringify(route)); + } + route.name = `${route.name}Parent`; + route.path = ''; + const meta = route.meta || {}; + meta.single = true; + meta.affix = false; + route.meta = meta; + } + } else { + warn('请正确配置路由:' + route?.name + '的component属性'); + } + route.children && asyncImportRoute(route.children); + }); + return routeList as unknown as T[]; +} + +/** + * Convert multi-level routing to level 2 routing + * 将多级路由转换为 2 级路由 + */ +export function flatMultiLevelRoutes(routeModules: AppRouteModule[]) { + const modules: AppRouteModule[] = cloneDeep(routeModules); + + for (let index = 0; index < modules.length; index++) { + const routeModule = modules[index]; + // 判断级别是否 多级 路由 + if (!isMultipleRoute(routeModule)) { + // 声明终止当前循环, 即跳过此次循环,进行下一轮 + continue; + } + // 路由等级提升 + promoteRouteLevel(routeModule); + } + return modules; +} + +// Routing level upgrade +// 路由等级提升 +function promoteRouteLevel(routeModule: AppRouteModule) { + // Use vue-router to splice menus + // 使用vue-router拼接菜单 + // createRouter 创建一个可以被 Vue 应用程序使用的路由实例 + let router: Router | null = createRouter({ + routes: [routeModule as unknown as RouteRecordNormalized], + history: createWebHashHistory(), + }); + // getRoutes: 获取所有 路由记录的完整列表。 + const routes = router.getRoutes(); + // 将所有子路由添加到二级路由 + addToChildren(routes, routeModule.children || [], routeModule); + router = null; + + // omit lodash的函数 对传入的item对象的children进行删除 + routeModule.children = routeModule.children?.map((item) => omit(item, 'children')); +} + +// Add all sub-routes to the secondary route +// 将所有子路由添加到二级路由 +function addToChildren( + routes: RouteRecordNormalized[], + children: AppRouteRecordRaw[], + routeModule: AppRouteModule, +) { + 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 AppRouteModule); + } + if (child.children?.length) { + addToChildren(routes, child.children, routeModule); + } + } +} + +// Determine whether the level exceeds 2 levels +// 判断级别是否超过2级 +function isMultipleRoute(routeModule: AppRouteModule) { + // Reflect.has 与 in 操作符 相同, 用于检查一个对象(包括它原型链上)是否拥有某个属性 + if (!routeModule || !Reflect.has(routeModule, 'children') || !routeModule.children?.length) { + return false; + } + + const children = routeModule.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; +} diff --git a/src/router/index.ts b/src/router/index.ts new file mode 100644 index 0000000..24edb71 --- /dev/null +++ b/src/router/index.ts @@ -0,0 +1,48 @@ +import type { RouteRecordRaw } from 'vue-router'; +import type { App } from 'vue'; + +import { createRouter, createWebHashHistory } from 'vue-router'; +import { basicRoutes } from './routes'; + +// 白名单应该包含基本静态路由 +const WHITE_NAME_LIST: string[] = []; +const getRouteNames = (array: any[]) => + array.forEach((item) => { + WHITE_NAME_LIST.push(item.name); + getRouteNames(item.children || []); + }); +getRouteNames(basicRoutes); + +// app router +// 创建一个可以被 Vue 应用程序使用的路由实例 +export const router = createRouter({ + // 创建一个 hash 历史记录。 + history: createWebHashHistory(import.meta.env.VITE_PUBLIC_PATH), + // 应该添加到路由的初始路由列表。 + routes: basicRoutes as unknown as RouteRecordRaw[], + // 是否应该禁止尾部斜杠。默认为假 + strict: true, + scrollBehavior: () => ({ left: 0, top: 0 }), +}); + +// reset router +export function resetRouter() { + router.getRoutes().forEach((route) => { + const { name } = route; + if (name && !WHITE_NAME_LIST.includes(name as string)) { + router.hasRoute(name) && router.removeRoute(name); + } + }); +} + +router.beforeEach((to: any, from: any, next: Function) => { + if (to.query && to.query.name) { + to.meta.title = to.query.name; + } + next(); +}); +// config router +// 配置路由器 +export function setupRouter(app: App) { + app.use(router); +} diff --git a/src/router/menus/index.ts b/src/router/menus/index.ts new file mode 100644 index 0000000..7ccdec9 --- /dev/null +++ b/src/router/menus/index.ts @@ -0,0 +1,137 @@ +import type { Menu, MenuModule } from '@/router/types'; +import type { RouteRecordNormalized } from 'vue-router'; + +import { useAppStoreWithOut } from '@/store/modules/app'; +import { usePermissionStore } from '@/store/modules/permission'; +import { transformMenuModule, getAllParentPath } from '@/router/helper/menuHelper'; +import { filter } from '@/utils/helper/treeHelper'; +import { isHttpUrl } from '@/utils/is'; +import { router } from '@/router'; +import { PermissionModeEnum } from '@/enums/appEnum'; +import { pathToRegexp } from 'path-to-regexp'; + +const modules = import.meta.glob('./modules/**/*.ts', { eager: true }); + +const menuModules: MenuModule[] = []; + +Object.keys(modules).forEach((key) => { + const mod = (modules as Recordable)[key].default || {}; + const modList = Array.isArray(mod) ? [...mod] : [mod]; + menuModules.push(...modList); +}); + +// =========================== +// ==========Helper=========== +// =========================== + +const getPermissionMode = () => { + const appStore = useAppStoreWithOut(); + return appStore.getProjectConfig.permissionMode; +}; +const isBackMode = () => { + return getPermissionMode() === PermissionModeEnum.BACK; +}; + +const isRouteMappingMode = () => { + return getPermissionMode() === PermissionModeEnum.ROUTE_MAPPING; +}; + +const isRoleMode = () => { + return getPermissionMode() === PermissionModeEnum.ROLE; +}; + +const staticMenus: Menu[] = []; +(() => { + menuModules.sort((a, b) => { + return (a.orderNo || 0) - (b.orderNo || 0); + }); + + for (const menu of menuModules) { + staticMenus.push(transformMenuModule(menu)); + } +})(); + +async function getAsyncMenus() { + const permissionStore = usePermissionStore(); + //递归过滤所有隐藏的菜单 + const menuFilter = (items) => { + return items.filter((item) => { + const show = !item.meta?.hideMenu && !item.hideMenu; + if (show && item.children) { + item.children = menuFilter(item.children); + } + return show; + }); + }; + if (isBackMode()) { + return menuFilter(permissionStore.getBackMenuList); + } + if (isRouteMappingMode()) { + // 333333 + return menuFilter(permissionStore.getFrontMenuList); + } + return staticMenus; +} + +export const getMenus = async (): Promise => { + const menus = await getAsyncMenus();//222222 + if (isRoleMode()) { + const routes = router.getRoutes(); + return filter(menus, basicFilter(routes)); + } + return menus; +}; + +export async function getCurrentParentPath(currentPath: string) { + const menus = await getAsyncMenus(); + const allParentPath = await getAllParentPath(menus, currentPath); + return allParentPath?.[0]; +} + +// Get the level 1 menu, delete children +export async function getShallowMenus(): Promise { + const menus = await getAsyncMenus(); + const shallowMenuList = menus.map((item) => ({ ...item, children: undefined })); + if (isRoleMode()) { + const routes = router.getRoutes(); + return shallowMenuList.filter(basicFilter(routes)); + } + return shallowMenuList; +} + +// Get the children of the menu +export async function getChildrenMenus(parentPath: string) { + const menus = await getMenus(); + const parent = menus.find((item) => item.path === parentPath); + if (!parent || !parent.children || !!parent?.meta?.hideChildrenInMenu) { + return [] as Menu[]; + } + if (isRoleMode()) { + const routes = router.getRoutes(); + return filter(parent.children, basicFilter(routes)); + } + return parent.children; +} + +function basicFilter(routes: RouteRecordNormalized[]) { + return (menu: Menu) => { + const matchRoute = routes.find((route) => { + if (isHttpUrl(menu.path)) return true; + + if (route.meta?.carryParam) { + return pathToRegexp(route.path).test(menu.path); + } + const isSame = route.path === menu.path; + if (!isSame) return false; + + if (route.meta?.ignoreAuth) return true; + + return isSame || pathToRegexp(route.path).test(menu.path); + }); + + if (!matchRoute) return false; + menu.icon = (menu.icon || matchRoute.meta.icon) as string; + menu.meta = matchRoute.meta; + return true; + }; +} diff --git a/src/router/routes/basic.ts b/src/router/routes/basic.ts new file mode 100644 index 0000000..ecf7597 --- /dev/null +++ b/src/router/routes/basic.ts @@ -0,0 +1,83 @@ +import type { AppRouteRecordRaw } from '@/router/types'; +import { t } from '@/hooks/web/useI18n'; +import { REDIRECT_NAME, LAYOUT, EXCEPTION_COMPONENT, PAGE_NOT_FOUND_NAME } from '@/router/constant'; + +// 404 on a page +export const PAGE_NOT_FOUND_ROUTE: AppRouteRecordRaw = { + path: '/:path(.*)*', + name: PAGE_NOT_FOUND_NAME + '11', + component: LAYOUT, + meta: { + title: 'ErrorPage', + hideBreadcrumb: true, + hideMenu: true, + }, + children: [ + { + path: '/:path(.*)*', + name: PAGE_NOT_FOUND_NAME, + component: EXCEPTION_COMPONENT, + meta: { + title: 'ErrorPage', + hideBreadcrumb: true, + hideMenu: true, + }, + }, + { + path: '/welcome', + name: PAGE_NOT_FOUND_NAME, + component: EXCEPTION_COMPONENT, + meta: { + title: 'Welcome', + hideBreadcrumb: true, + hideMenu: true, + }, + }, + ], +}; + +export const REDIRECT_ROUTE: AppRouteRecordRaw = { + path: '/redirect', + component: LAYOUT, + name: 'RedirectTo', + meta: { + title: REDIRECT_NAME, + hideBreadcrumb: true, + hideMenu: true, + }, + children: [ + { + path: '/redirect/:path(.*)/:_redirect_type(.*)/:_origin_params(.*)?', + name: REDIRECT_NAME, + component: () => import('@/views/sys/redirect/index.vue'), + meta: { + title: REDIRECT_NAME, + hideBreadcrumb: true, + }, + }, + ], +}; + +export const ERROR_LOG_ROUTE: AppRouteRecordRaw = { + path: '/error-log', + name: 'ErrorLog', + component: LAYOUT, + redirect: '/error-log/list', + meta: { + title: 'ErrorLog', + hideBreadcrumb: true, + hideChildrenInMenu: true, + }, + children: [ + { + path: 'list', + name: 'ErrorLogList', + component: () => import('@/views/sys/error-log/index.vue'), + meta: { + title: t('routes.basic.errorLogList'), + hideBreadcrumb: true, + currentActiveMenu: '/error-log', + }, + }, + ], +}; diff --git a/src/router/routes/index.ts b/src/router/routes/index.ts new file mode 100644 index 0000000..4fd00b1 --- /dev/null +++ b/src/router/routes/index.ts @@ -0,0 +1,119 @@ +import type { AppRouteRecordRaw, AppRouteModule } from '@/router/types'; + +import { PAGE_NOT_FOUND_ROUTE, REDIRECT_ROUTE } from '@/router/routes/basic'; +import { LAYOUT } from '@/router/constant'; + +import { mainOutRoutes } from './mainOut'; +import { PageEnum } from '@/enums/pageEnum'; +import { t } from '@/hooks/web/useI18n'; + +// import.meta.glob() 直接引入所有的模块 Vite 独有的功能 +const modules = import.meta.glob('./modules/**/*.ts', { eager: true }); +const routeModuleList: AppRouteModule[] = []; + +// 加入到路由集合中 +Object.keys(modules).forEach((key) => { + const mod = (modules as Recordable)[key].default || {}; + if (mod.meta) { + const modList = Array.isArray(mod) ? [...mod] : [mod]; + routeModuleList.push(...modList); + } +}); + +export const asyncRoutes = [PAGE_NOT_FOUND_ROUTE, ...routeModuleList]; + +// 根路由 +export const RootRoute: AppRouteRecordRaw = { + path: '/', + name: 'Root', + redirect: PageEnum.BASE_HOME, + meta: { + title: 'Root', + }, +}; + +export const LoginRoute: AppRouteRecordRaw = { + path: '/login', + name: 'Login', + component: () => import('@/views/sys/login/Login.vue'), + meta: { + title: t('routes.basic.login'), + }, +}; +export const H5HtmlRoute: AppRouteRecordRaw = { + path: '/h5html', + name: 'h5html', + component: () => import('@/views/demo/h5html/index.vue'), + meta: { + title: 'H5表单', + }, +}; + +export const CreatePreviewRoute: AppRouteRecordRaw = { + path: '/create_preview', + name: 'create_preview', + component: () => import('@/views/demo/workflow/h5/create.vue'), + meta: { + title: t('routes.demo.workflow.create_preview'), + }, +}; +export const TaskAuditRoute: AppRouteRecordRaw = { + path: '/task_audit_preview', + name: 'task_audit_preview', + component: () => import('@/views/demo/workflow/h5/audit.vue'), + meta: { + title: t('routes.demo.workflow.task_audit_preview'), + }, +}; +export const TaskLookRoute: AppRouteRecordRaw = { + path: '/task_look_preview', + name: 'task_look_preview', + component: () => import('@/views/demo/workflow/h5/look.vue'), + meta: { + title: t('routes.demo.workflow.task_look_preview'), + }, +}; +export const SchemeRoute: AppRouteRecordRaw = { + path: '/scheme_preview', + name: 'scheme_preview', + component: () => import('@/views/demo/workflow/h5/scheme.vue'), + meta: { + title: t('routes.demo.workflow.scheme_preview'), + }, +}; +export const FORMCALLPAGE_ROUTE: AppRouteRecordRaw = { + path: '/formCallPageParent', + component: LAYOUT, + name: 'formCallPageParent', + meta: { + title: '表单', + hideBreadcrumb: true, + hideMenu: true, + }, + children: [ + { + path: '/formCallPage', + name: 'formCallPage', + component: () => import('@/views/demo/onlineform/formCall/index.vue'), + meta: { + title: '表单调用', + hideBreadcrumb: true, + }, + }, + ], +}; +// Basic routing without permission +// 未经许可的基本路由 +export const basicRoutes = [ + H5HtmlRoute, + LoginRoute, + RootRoute, + ...mainOutRoutes, + REDIRECT_ROUTE, + PAGE_NOT_FOUND_ROUTE, + CreatePreviewRoute, + TaskAuditRoute, + TaskLookRoute, + SchemeRoute, + FORMCALLPAGE_ROUTE, +]; diff --git a/src/router/routes/mainOut.ts b/src/router/routes/mainOut.ts new file mode 100644 index 0000000..6e2a4a4 --- /dev/null +++ b/src/router/routes/mainOut.ts @@ -0,0 +1,22 @@ +/** +The routing of this file will not show the layout. +It is an independent new page. +the contents of the file still need to log in to access + */ +import type { AppRouteModule } from '@/router/types'; + +// test +// http:ip:port/main-out +export const mainOutRoutes: AppRouteModule[] = [ + { + path: '/main-out', + name: 'MainOut', + component: () => import('@/views/demo/main-out/index.vue'), + meta: { + title: 'MainOut', + ignoreAuth: true, + }, + }, +]; + +export const mainOutRouteNames = mainOutRoutes.map((item) => item.name); diff --git a/src/router/routes/modules/dashboard.ts b/src/router/routes/modules/dashboard.ts new file mode 100644 index 0000000..e28e9b3 --- /dev/null +++ b/src/router/routes/modules/dashboard.ts @@ -0,0 +1,28 @@ +import type { AppRouteModule } from '@/router/types'; + +import { LAYOUT } from '@/router/constant'; +import { t } from '@/hooks/web/useI18n'; + +const dashboard: AppRouteModule = { + path: '/dashboard', + name: 'Dashboard', + component: LAYOUT, + redirect: '/dashboard/analysis', + meta: { + orderNo: 10, + icon: 'ion:grid-outline', + title: t('routes.dashboard.dashboard'), + }, + children: [ + { + path: '/dashboard/analysis', + name: 'Analysis', + meta: { + title: t('routes.dashboard.analysis'), + }, + component: () => import('@/views/home/index.vue'), + }, + ], +}; + +export default dashboard; diff --git a/src/router/routes/modules/demo/charts.ts b/src/router/routes/modules/demo/charts.ts new file mode 100644 index 0000000..4730296 --- /dev/null +++ b/src/router/routes/modules/demo/charts.ts @@ -0,0 +1,46 @@ + +import type { AppRouteModule } from '@/router/types'; + +import { LAYOUT } from '@/router/constant'; +import { t } from '@/hooks/web/useI18n'; + +const charts: AppRouteModule = { + path: '/charts', + name: 'Charts', + component: LAYOUT, + redirect: '/charts/echarts/map', + meta: { + orderNo: 500, + icon: 'ion:bar-chart-outline', + title: t('routes.demo.charts.charts'), + }, + children: [ + { + path: 'baiduMap', + name: 'BaiduMap', + meta: { + title: t('routes.demo.charts.baiduMap'), + }, + component: () => import('@/views/demo/charts/map/Baidu.vue'), + }, + { + path: 'mars3d', + name: 'mars3d', + meta: { + title: t('routes.demo.charts.mars3d'), + ignoreKeepAlive: true, + }, + component: () => import('@/views/demo/charts/mars3d/index.vue'), + }, + // { + // path: 'marsgis', + // name: 'Marsgis', + // meta: { + // title: 'Mars3D地图', + // }, + // component: () => import('@/mars/views/index.vue'), + // }, + ], +}; + +// export default charts; diff --git a/src/router/routes/modules/demo/iframe.ts b/src/router/routes/modules/demo/iframe.ts new file mode 100644 index 0000000..a2efed7 --- /dev/null +++ b/src/router/routes/modules/demo/iframe.ts @@ -0,0 +1,49 @@ +import type { AppRouteModule } from '@/router/types'; + +import { LAYOUT } from '@/router/constant'; +import { t } from '@/hooks/web/useI18n'; + +const IFrame = () => import('@/views/sys/iframe/FrameBlank.vue'); + +const iframe: AppRouteModule = { + path: '/frame', + name: 'Frame', + component: LAYOUT, + redirect: '/frame/doc', + meta: { + orderNo: 1000, + icon: 'ion:tv-outline', + title: t('routes.demo.iframe.frame'), + }, + + children: [ + { + path: 'doc', + name: 'Doc', + component: IFrame, + meta: { + frameSrc: 'https://doc.vvbin.cn/', + title: t('routes.demo.iframe.doc'), + }, + }, + { + path: 'antv', + name: 'Antv', + component: IFrame, + meta: { + frameSrc: 'https://www.antdv.com/docs/vue/introduce-cn/', + title: t('routes.demo.iframe.antv'), + }, + }, + { + path: 'https://doc.vvbin.cn/', + name: 'DocExternal', + component: IFrame, + meta: { + title: t('routes.demo.iframe.docExternal'), + }, + }, + ], +}; + +// export default iframe; diff --git a/src/router/routes/modules/demo/level.ts b/src/router/routes/modules/demo/level.ts new file mode 100644 index 0000000..60140cb --- /dev/null +++ b/src/router/routes/modules/demo/level.ts @@ -0,0 +1,68 @@ +import type { AppRouteModule } from '@/router/types'; + +import { getParentLayout, LAYOUT } from '@/router/constant'; +import { t } from '@/hooks/web/useI18n'; + +const permission: AppRouteModule = { + path: '/level', + name: 'Level', + component: LAYOUT, + redirect: '/level/menu1/menu1-1/menu1-1-1', + meta: { + orderNo: 2000, + icon: 'ion:menu-outline', + title: t('routes.demo.level.level'), + }, + + children: [ + { + path: 'menu1', + name: 'Menu1Demo', + component: getParentLayout('Menu1Demo'), + meta: { + title: 'Menu1', + }, + redirect: '/level/menu1/menu1-1/menu1-1-1', + children: [ + { + path: 'menu1-1', + name: 'Menu11Demo', + component: getParentLayout('Menu11Demo'), + meta: { + title: 'Menu1-1', + }, + redirect: '/level/menu1/menu1-1/menu1-1-1', + children: [ + { + path: 'menu1-1-1', + name: 'Menu111Demo', + component: () => import('@/views/demo/level/Menu111.vue'), + meta: { + title: 'Menu111', + }, + }, + ], + }, + { + path: 'menu1-2', + name: 'Menu12Demo', + component: () => import('@/views/demo/level/Menu12.vue'), + meta: { + title: 'Menu1-2', + }, + }, + ], + }, + { + path: 'menu2', + name: 'Menu2Demo', + component: () => import('@/views/demo/level/Menu2.vue'), + meta: { + title: 'Menu2', + // ignoreKeepAlive: true, + }, + }, + ], +}; + +// export default permission; diff --git a/src/router/routes/modules/demo/permission.ts b/src/router/routes/modules/demo/permission.ts new file mode 100644 index 0000000..8993e81 --- /dev/null +++ b/src/router/routes/modules/demo/permission.ts @@ -0,0 +1,92 @@ +import type { AppRouteModule } from '@/router/types'; + +import { getParentLayout, LAYOUT } from '@/router/constant'; +import { RoleEnum } from '@/enums/roleEnum'; +import { t } from '@/hooks/web/useI18n'; + +const permission: AppRouteModule = { + path: '/permission', + name: 'Permission', + component: LAYOUT, + redirect: '/permission/front/page', + meta: { + orderNo: 15, + icon: 'ion:key-outline', + title: t('routes.demo.permission.permission'), + }, + + children: [ + { + path: 'front', + name: 'PermissionFrontDemo', + component: getParentLayout('PermissionFrontDemo'), + meta: { + title: t('routes.demo.permission.front'), + }, + children: [ + { + path: 'page', + name: 'FrontPageAuth', + component: () => import('@/views/demo/permission/front/index.vue'), + meta: { + title: t('routes.demo.permission.frontPage'), + }, + }, + { + path: 'btn', + name: 'FrontBtnAuth', + component: () => import('@/views/demo/permission/front/Btn.vue'), + meta: { + title: t('routes.demo.permission.frontBtn'), + }, + }, + { + path: 'auth-pageA', + name: 'FrontAuthPageA', + component: () => import('@/views/demo/permission/front/AuthPageA.vue'), + meta: { + title: t('routes.demo.permission.frontTestA'), + roles: [RoleEnum.SUPER], + }, + }, + { + path: 'auth-pageB', + name: 'FrontAuthPageB', + component: () => import('@/views/demo/permission/front/AuthPageB.vue'), + meta: { + title: t('routes.demo.permission.frontTestB'), + roles: [RoleEnum.TEST], + }, + }, + ], + }, + { + path: 'back', + name: 'PermissionBackDemo', + component: getParentLayout('PermissionBackDemo'), + meta: { + title: t('routes.demo.permission.back'), + }, + children: [ + { + path: 'page', + name: 'BackAuthPage', + component: () => import('@/views/demo/permission/back/index.vue'), + meta: { + title: t('routes.demo.permission.backPage'), + }, + }, + { + path: 'btn', + name: 'BackAuthBtn', + component: () => import('@/views/demo/permission/back/Btn.vue'), + meta: { + title: t('routes.demo.permission.backBtn'), + }, + }, + ], + }, + ], +}; + +// export default permission; diff --git a/src/router/routes/modules/demo/system.ts b/src/router/routes/modules/demo/system.ts new file mode 100644 index 0000000..579a277 --- /dev/null +++ b/src/router/routes/modules/demo/system.ts @@ -0,0 +1,97 @@ +import type { AppRouteModule } from '@/router/types'; + +import { LAYOUT } from '@/router/constant'; +import { t } from '@/hooks/web/useI18n'; + +const system: AppRouteModule = { + path: '/system', + name: 'System', + component: LAYOUT, + redirect: '/system/account', + meta: { + orderNo: 2000, + icon: 'ion:settings-outline', + title: t('routes.demo.system.moduleName'), + }, + children: [ + { + path: 'account', + name: 'AccountManagement', + meta: { + title: t('routes.demo.system.account'), + ignoreKeepAlive: false, + }, + component: () => import('@/views/demo/system/account/index.vue'), + }, + { + path: 'vxeTableAccount', + name: 'VxeTableAccountManagement', + meta: { + title: t('routes.demo.system.vxeTableAccount'), + ignoreKeepAlive: false, + }, + component: () => import('@/views/demo/system/vxe-account/index.vue'), + }, + { + path: 'account_detail/:id', + name: 'AccountDetail', + meta: { + hideMenu: true, + title: t('routes.demo.system.account_detail'), + ignoreKeepAlive: true, + showMenu: false, + currentActiveMenu: '/system/account', + }, + component: () => import('@/views/demo/system/account/AccountDetail.vue'), + }, + { + path: 'role', + name: 'RoleManagement', + meta: { + title: t('routes.demo.system.role'), + ignoreKeepAlive: true, + }, + component: () => import('@/views/demo/system/role/index.vue'), + }, + + { + path: 'menu', + name: 'MenuManagement', + meta: { + title: t('routes.demo.system.menu'), + ignoreKeepAlive: true, + }, + component: () => import('@/views/demo/system/menu/index.vue'), + }, + { + path: 'dept', + name: 'DeptManagement', + meta: { + title: t('routes.demo.system.dept'), + ignoreKeepAlive: true, + }, + component: () => import('@/views/demo/system/dept/index.vue'), + }, + { + path: 'changePassword', + name: 'ChangePassword', + meta: { + title: t('routes.demo.system.password'), + ignoreKeepAlive: true, + }, + component: () => import('@/views/demo/system/password/index.vue'), + }, + { + path: 'position', + name: 'PositionManagement', + meta: { + title: t('routes.demo.system.position'), + ignoreKeepAlive: true, + }, + component: () => import('@/views/demo/system/position/index.vue'), + }, + + ], +}; + +// export default system; diff --git a/src/router/types.ts b/src/router/types.ts new file mode 100644 index 0000000..85a2d36 --- /dev/null +++ b/src/router/types.ts @@ -0,0 +1,60 @@ +import type { RouteRecordRaw, RouteMeta } from 'vue-router'; +import { RoleEnum } from '@/enums/roleEnum'; +import { defineComponent } from 'vue'; + +export type Component = + | ReturnType + | (() => Promise) + | (() => Promise); + +// @ts-ignore +export interface AppRouteRecordRaw extends Omit { + name: string; + meta: RouteMeta; + component?: Component | string; + components?: Component; + children?: AppRouteRecordRaw[]; + props?: Recordable; + fullPath?: string; +} + +export interface MenuTag { + type?: 'primary' | 'error' | 'warn' | 'success'; + content?: string; + dot?: boolean; +} + +export interface Menu { + name: string; + + icon?: string; + + img?: string; + + path: string; + + // path contains param, auto assignment. + paramPath?: string; + + disabled?: boolean; + + children?: Menu[]; + + orderNo?: number; + + roles?: RoleEnum[]; + + meta?: Partial; + + tag?: MenuTag; + + hideMenu?: boolean; +} + +export interface MenuModule { + orderNo?: number; + menu: Menu; +} + +// export type AppRouteModule = RouteModule | AppRouteRecordRaw; +export type AppRouteModule = AppRouteRecordRaw; diff --git a/src/settings/componentSetting.ts b/src/settings/componentSetting.ts new file mode 100644 index 0000000..82ed84e --- /dev/null +++ b/src/settings/componentSetting.ts @@ -0,0 +1,97 @@ +// Used to configure the general configuration of some components without modifying the components + +import type { SorterResult } from '../components/Table'; + +export default { + // basic-table setting + table: { + // Form interface request general configuration + // support xxx.xxx.xxx + fetchSetting: { + // The field name of the current page passed to the background + pageField: 'page', + // The number field name of each page displayed in the background + sizeField: 'limit', + // Field name of the form data returned by the interface + listField: 'items', + // Total number of tables returned by the interface field name + totalField: 'total', + }, + // Number of pages that can be selected + pageSizeOptions: ['10', '50', '80', '100'], + // Default display quantity on one page + defaultPageSize: 10, + // Default Size + defaultSize: 'middle', + // Custom general sort function + defaultSortFn: (sortInfo: SorterResult) => { + const { field, order } = sortInfo; + if (field && order) { + return { + // The sort field passed to the backend you + field, + // Sorting method passed to the background asc/desc + order, + }; + } else { + return {}; + } + }, + // Custom general filter function + defaultFilterFn: (data: Partial>) => { + return data; + }, + }, + vxeTable: { + table: { + border: true, + stripe: true, + columnConfig: { + resizable: true, + isCurrent: true, + isHover: true, + }, + rowConfig: { + isCurrent: true, + isHover: true, + }, + emptyRender: { + name: 'AEmpty', + }, + printConfig: {}, + exportConfig: {}, + customConfig: { + storage: true, + }, + }, + grid: { + toolbarConfig: { + enabled: true, + export: true, + zoom: true, + print: true, + refresh: true, + custom: true, + }, + pagerConfig: { + pageSizes: [20, 50, 100, 500], + pageSize: 20, + autoHidden: true, + }, + proxyConfig: { + form: true, + props: { + result: 'items', + total: 'total', + }, + }, + zoomConfig: {}, + }, + }, + // scrollbar setting + scrollbar: { + // Whether to use native scroll bar + // After opening, the menu, modal, drawer will change the pop-up scroll bar to native + native: false, + }, +}; diff --git a/src/settings/designSetting.ts b/src/settings/designSetting.ts new file mode 100644 index 0000000..ede11d4 --- /dev/null +++ b/src/settings/designSetting.ts @@ -0,0 +1,57 @@ +import { ThemeEnum } from '../enums/appEnum'; + +export const prefixCls = 'vben'; + +export const multipleTabHeight = 30; + +export const darkMode = ThemeEnum.LIGHT; + +// 页脚固定高度 +export const footerHeight = 75; + +// .@{namespace}-layout-multiple-header__placeholder +// 全屏页头动画时长 +export const layoutMultipleHeadePlaceholderTime = 0.6; + +// app theme preset color +export const APP_PRESET_COLOR_LIST: string[] = [ + '#0960bd', + '#0084f4', + '#009688', + '#536dfe', + '#ff5c93', + '#ee4f12', + '#0096c7', + '#9c27b0', + '#ff9800', +]; + +// header preset color +export const HEADER_PRESET_BG_COLOR_LIST: string[] = [ + '#ffffff', + '#151515', + '#009688', + '#5172DC', + '#018ffb', + '#409eff', + '#e74c3c', + '#24292e', + '#394664', + '#001529', + '#383f45', +]; + +// sider preset color +export const SIDE_BAR_BG_COLOR_LIST: string[] = [ + '#001529', + '#212121', + '#273352', + '#ffffff', + '#191b24', + '#191a23', + '#304156', + '#001628', + '#28333E', + '#344058', + '#383f45', +]; diff --git a/src/settings/encryptionSetting.ts b/src/settings/encryptionSetting.ts new file mode 100644 index 0000000..e8b177d --- /dev/null +++ b/src/settings/encryptionSetting.ts @@ -0,0 +1,13 @@ +import { isDevMode } from '@/utils/env'; + +// System default cache time, in seconds +export const DEFAULT_CACHE_TIME = 60 * 60 * 24 * 7; + +// aes encryption key +export const cacheCipher = { + key: '_11111000001111@', + iv: '@11111000001111_', +}; + +// Whether the system cache is encrypted using aes +export const SHOULD_ENABLE_STORAGE_ENCRYPTION = !isDevMode(); diff --git a/src/settings/localeSetting.ts b/src/settings/localeSetting.ts new file mode 100644 index 0000000..c73420a --- /dev/null +++ b/src/settings/localeSetting.ts @@ -0,0 +1,29 @@ +import type { DropMenu } from '../components/Dropdown'; +import type { LocaleSetting, LocaleType } from '#/config'; + +export const LOCALE: { [key: string]: LocaleType } = { + ZH_CN: 'zh_CN', + EN_US: 'en', +}; + +export const localeSetting: LocaleSetting = { + showPicker: true, + // Locale + locale: LOCALE.ZH_CN, + // Default locale + fallback: LOCALE.ZH_CN, + // available Locales + availableLocales: [LOCALE.ZH_CN, LOCALE.EN_US], +}; + +// locale list +export const localeList: DropMenu[] = [ + { + text: '简体中文', + event: LOCALE.ZH_CN, + }, + { + text: 'English', + event: LOCALE.EN_US, + }, +]; diff --git a/src/settings/projectSetting.ts b/src/settings/projectSetting.ts new file mode 100644 index 0000000..65e0752 --- /dev/null +++ b/src/settings/projectSetting.ts @@ -0,0 +1,188 @@ +import type { ProjectConfig } from '#/config'; +import { MenuTypeEnum, MenuModeEnum, TriggerEnum, MixSidebarTriggerEnum } from '@/enums/menuEnum'; +import { CacheTypeEnum } from '@/enums/cacheEnum'; +import { + ContentEnum, + PermissionModeEnum, + ThemeEnum, + RouterTransitionEnum, + SettingButtonPositionEnum, + SessionTimeoutProcessingEnum, +} from '@/enums/appEnum'; +import { + SIDE_BAR_BG_COLOR_LIST, + HEADER_PRESET_BG_COLOR_LIST, + APP_PRESET_COLOR_LIST, +} from './designSetting'; + +// ! You need to clear the browser cache after the change +const setting: ProjectConfig = { + //是否显示配置按钮 + showSettingButton: true, + + // 是否显示主题切换按钮 + showDarkModeToggle: true, + + // “设置”按钮的位置 + settingButtonPosition: SettingButtonPositionEnum.AUTO, + + // 权限模式 + permissionMode: PermissionModeEnum.ROUTE_MAPPING, + + // 与权限相关的缓存存储在sessionStorage或localStorage中 + permissionCacheType: CacheTypeEnum.LOCAL, + + // 会话超时处理 + sessionTimeoutProcessing: SessionTimeoutProcessingEnum.ROUTE_JUMP, + + // 颜色 + themeColor: APP_PRESET_COLOR_LIST[0], + + // Website gray mode, open for possible mourning dates + grayMode: false, + + // Color Weakness Mode + colorWeak: false, + + // Whether to cancel the menu, the top, the multi-tab page display, for possible embedded in other systems + fullContent: false, + + // content mode + contentMode: ContentEnum.FULL, + + // Whether to display the logo + showLogo: true, + + // Whether to show footer + showFooter: false, + + // Header configuration + headerSetting: { + // header bg color + bgColor: HEADER_PRESET_BG_COLOR_LIST[0], + // Fixed at the top + fixed: true, + // Whether to show top + show: true, + // theme + theme: ThemeEnum.LIGHT, + // Whether to enable the lock screen function + useLockPage: true, + // Whether to show the full screen button + showFullScreen: true, + // Whether to show the document button + showDoc: true, + // Whether to show the notification button + showNotice: true, + // Whether to display the menu search + showSearch: true, + showApi: true, + }, + + // Menu configuration + menuSetting: { + // sidebar menu bg color + bgColor: SIDE_BAR_BG_COLOR_LIST[0], + // 是否固定左侧菜单 + fixed: true, + // 菜单折叠 + collapsed: false, + // When sider hide because of the responsive layout + siderHidden: false, + // 折叠菜单时是否显示菜单名称 + collapsedShowTitle: true, + //是否可以拖动 + //仅限于打开左侧菜单,鼠标在菜单右侧有一个拖动条 + canDrag: false, + // 是否显示无dom + show: true, + // Whether to show dom + hidden: true, + // Menu width + menuWidth: 210, + // Menu mode + mode: MenuModeEnum.HORIZONTAL, + // Menu type + type: MenuTypeEnum.TOP_MENU, + // Menu theme + theme: ThemeEnum.DARK, + // Split menu + split: false, + // Top menu layout + topMenuAlign: 'center', + // Fold trigger position + trigger: TriggerEnum.HEADER, + // Turn on accordion mode, only show a menu + accordion: true, + // Switch page to close menu + closeMixSidebarOnChange: false, + // Module opening method ‘click’ |'hover' + mixSideTrigger: MixSidebarTriggerEnum.CLICK, + // Fixed expanded menu + mixSideFixed: false, + }, + + // Multi-label + multiTabsSetting: { + cache: false, + // Turn on + show: true, + // Is it possible to drag and drop sorting tabs + canDrag: true, + // Turn on quick actions + showQuick: true, + // Whether to show the refresh button + showRedo: true, + // Whether to show the collapse button + showFold: true, + // Auto collapsed + autoCollapse: false, + }, + + // Transition Setting + transitionSetting: { + // Whether to open the page switching animation + // The disabled state will also disable pageLoading + enable: true, + + // Route basic switching animation + basicTransition: RouterTransitionEnum.FADE_SIDE, + + // Whether to open page switching loading + // Only open when enable=true + openPageLoading: true, + + // Whether to open the top progress bar + openNProgress: false, + }, + + // Whether to enable KeepAlive cache is best to close during development, otherwise the cache needs to be cleared every time + openKeepAlive: true, + + // Automatic screen lock time, 0 does not lock the screen. Unit minute default 0 + lockTime: 0, + + // Whether to show breadcrumbs + showBreadCrumb: true, + + // Whether to show the breadcrumb icon + showBreadCrumbIcon: false, + + // Use error-handler-plugin + useErrorHandle: false, + + // Whether to open back to top + useOpenBackTop: true, + + // Is it possible to embed iframe pages + canEmbedIFramePage: true, + + // Whether to delete unclosed messages and notify when switching the interface + closeMessageOnSwitch: true, + + // Whether to cancel the http request that has been sent but not responded when switching the interface. + // If it is enabled, I want to overwrite a single interface. Can be set in a separate interface + removeAllHttpPending: false, +}; + +export default setting; diff --git a/src/settings/siteSetting.ts b/src/settings/siteSetting.ts new file mode 100644 index 0000000..19e195a --- /dev/null +++ b/src/settings/siteSetting.ts @@ -0,0 +1,8 @@ +// github repo url +export const GITHUB_URL = 'https://github.com/anncwb/vue-vben-admin'; + +// vue-vben-admin-next-doc +export const DOC_URL = 'https://doc.vvbin.cn/'; + +// site url +export const SITE_URL = 'https://vben.vvbin.cn/'; diff --git a/src/store/index.ts b/src/store/index.ts new file mode 100644 index 0000000..2b40f50 --- /dev/null +++ b/src/store/index.ts @@ -0,0 +1,11 @@ +import type { App } from 'vue'; +import { createPinia } from 'pinia'; +import { registerPiniaPersistPlugin } from '@/store/plugin/persist'; + +const store = createPinia(); +registerPiniaPersistPlugin(store); + +export function 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 0000000..df55b00 --- /dev/null +++ b/src/store/modules/app.ts @@ -0,0 +1,118 @@ +import type { + ProjectConfig, + HeaderSetting, + MenuSetting, + TransitionSetting, + MultiTabsSetting, +} from '#/config'; +import type { BeforeMiniState, ApiAddress } from '#/store'; + +import { defineStore } from 'pinia'; +import { store } from '@/store'; + +import { ThemeEnum } from '@/enums/appEnum'; +import { APP_DARK_MODE_KEY, PROJ_CFG_KEY, API_ADDRESS } from '@/enums/cacheEnum'; +import { Persistent } from '@/utils/cache/persistent'; +import { darkMode } from '@/settings/designSetting'; +import { resetRouter } from '@/router'; +import { deepMerge } from '@/utils'; + +interface AppState { + darkMode?: ThemeEnum; + // Page loading status + pageLoading: boolean; + // project config + projectConfig: ProjectConfig | null; + // When the window shrinks, remember some states, and restore these states when the window is restored + beforeMiniInfo: BeforeMiniState; +} +let timeId: TimeoutHandle; +export const useAppStore = defineStore({ + id: 'app', + state: (): AppState => ({ + darkMode: undefined, + pageLoading: false, + projectConfig: Persistent.getLocal(PROJ_CFG_KEY), + beforeMiniInfo: {}, + }), + getters: { + getPageLoading(state): boolean { + return state.pageLoading; + }, + getDarkMode(state): 'light' | 'dark' | string { + return state.darkMode || localStorage.getItem(APP_DARK_MODE_KEY) || darkMode; + }, + + getBeforeMiniInfo(state): BeforeMiniState { + return state.beforeMiniInfo; + }, + + getProjectConfig(state): ProjectConfig { + return state.projectConfig || ({} as ProjectConfig); + }, + + getHeaderSetting(): HeaderSetting { + return this.getProjectConfig.headerSetting; + }, + getMenuSetting(): MenuSetting { + return this.getProjectConfig.menuSetting; + }, + getTransitionSetting(): TransitionSetting { + return this.getProjectConfig.transitionSetting; + }, + getMultiTabsSetting(): MultiTabsSetting { + return this.getProjectConfig.multiTabsSetting; + }, + getApiAddress() { + return JSON.parse(localStorage.getItem(API_ADDRESS) || '{}'); + }, + }, + actions: { + setPageLoading(loading: boolean): void { + this.pageLoading = loading; + }, + + setDarkMode(mode: ThemeEnum): void { + this.darkMode = mode; + localStorage.setItem(APP_DARK_MODE_KEY, mode); + }, + + setBeforeMiniInfo(state: BeforeMiniState): void { + this.beforeMiniInfo = state; + }, + + setProjectConfig(config: DeepPartial): void { + this.projectConfig = deepMerge(this.projectConfig || {}, config) as ProjectConfig; + Persistent.setLocal(PROJ_CFG_KEY, this.projectConfig); + }, + setMenuSetting(setting: Partial): void { + this.projectConfig!.menuSetting = deepMerge(this.projectConfig!.menuSetting, setting); + Persistent.setLocal(PROJ_CFG_KEY, this.projectConfig); + }, + + async resetAllState() { + resetRouter(); + Persistent.clearAll(); + }, + async setPageLoadingAction(loading: boolean): Promise { + if (loading) { + clearTimeout(timeId); + // Prevent flicker + timeId = setTimeout(() => { + this.setPageLoading(loading); + }, 50); + } else { + this.setPageLoading(loading); + clearTimeout(timeId); + } + }, + setApiAddress(config: ApiAddress): void { + localStorage.setItem(API_ADDRESS, JSON.stringify(config)); + }, + }, +}); + +// Need to be used outside the setup +export function useAppStoreWithOut() { + return useAppStore(store); +} diff --git a/src/store/modules/cloudquery.ts b/src/store/modules/cloudquery.ts new file mode 100644 index 0000000..f97dbf3 --- /dev/null +++ b/src/store/modules/cloudquery.ts @@ -0,0 +1,71 @@ +import { defineStore } from 'pinia'; + +export const useCloudQueryStore = defineStore({ + id: 'cloudquery', + state: () => ({ + // 当前云查询查询的 + beforeId: '', + geomid: '', + caseno: '', + // 程序锁标识 + identification: false, + // 云查询信息 + cloudqueryInfo: {}, + // 云查询结果展示 + cloudQueryModalInfo: { + basicQuery: { + landClassify: {}, + plowLandOccupy: {}, + }, + timeImages: {}, + }, + // 云查询提示信息 + cloudQueryVisible: false, + }), + getters: { + getBeforeId: (state) => { + return state.beforeId; + }, + getGeomid: (state) => { + return state.geomid; + }, + getCaseno: (state) => { + return state.caseno; + }, + getCloudQueryInfo: (state) => { + return state.cloudqueryInfo; + }, + getIdentification: (state) => { + return state.identification; + }, + getCloudQueryModalInfo: (state) => { + return state.cloudQueryModalInfo; + }, + getCloudQueryVisable: (state) => { + return state.cloudQueryVisible; + }, + }, + actions: { + setBeforeId(info: any) { + this.beforeId = info; + }, + setGeomid(info: any) { + this.geomid = info; + }, + setCaseno(info: any) { + this.caseno = info; + }, + setCloudQueryInfo(info: any) { + this.cloudqueryInfo = info; + }, + setIdentification(state: boolean) { + this.identification = state; + }, + setCloudQueryModalInfo(data: any) { + this.cloudQueryModalInfo = data; + }, + setCloudQueryVisable(data: any) { + this.cloudQueryVisible = data; + }, + }, +}); diff --git a/src/store/modules/errorLog.ts b/src/store/modules/errorLog.ts new file mode 100644 index 0000000..b758c8f --- /dev/null +++ b/src/store/modules/errorLog.ts @@ -0,0 +1,77 @@ +import type { ErrorLogInfo } from '#/store'; + +import { defineStore } from 'pinia'; +import { store } from '@/store'; + +import { formatToDateTime } from '@/utils/dateUtil'; +import projectSetting from '@/settings/projectSetting'; + +import { ErrorTypeEnum } from '@/enums/exceptionEnum'; + +export interface ErrorLogState { + errorLogInfoList: Nullable; + errorLogListCount: number; +} + +export const useErrorLogStore = defineStore({ + id: 'app-error-log', + state: (): ErrorLogState => ({ + errorLogInfoList: null, + errorLogListCount: 0, + }), + getters: { + getErrorLogInfoList(state): ErrorLogInfo[] { + return state.errorLogInfoList || []; + }, + getErrorLogListCount(state): number { + return state.errorLogListCount; + }, + }, + actions: { + addErrorLogInfo(info: ErrorLogInfo) { + const item = { + ...info, + time: formatToDateTime(new Date()), + }; + this.errorLogInfoList = [item, ...(this.errorLogInfoList || [])]; + this.errorLogListCount += 1; + }, + + setErrorLogListCount(count: number): void { + this.errorLogListCount = count; + }, + + /** + * Triggered after ajax request error + * @param error + * @returns + */ + addAjaxErrorInfo(error) { + const { useErrorHandle } = projectSetting; + if (!useErrorHandle) { + return; + } + const errInfo: Partial = { + message: error.message, + type: ErrorTypeEnum.AJAX, + }; + if (error.response) { + const { + config: { url = '', data: params = '', method = 'get', headers = {} } = {}, + data = {}, + } = error.response; + errInfo.url = url; + errInfo.name = 'Ajax Error!'; + errInfo.file = '-'; + errInfo.stack = JSON.stringify(data); + errInfo.detail = JSON.stringify({ params, method, headers }); + } + this.addErrorLogInfo(errInfo as ErrorLogInfo); + }, + }, +}); + +// Need to be used outside the setup +export function useErrorLogStoreWithOut() { + return useErrorLogStore(store); +} diff --git a/src/store/modules/flow.ts b/src/store/modules/flow.ts new file mode 100644 index 0000000..8c01616 --- /dev/null +++ b/src/store/modules/flow.ts @@ -0,0 +1,61 @@ +import { defineStore } from 'pinia'; + +export const flowStore = defineStore({ + id: 'flow', + state: () => ({ + flowWfData: [], + flowElements: [], + }), + getters: { + getWfData(state) { + return state.flowWfData; + }, + getFlowElments(state) { + return state.flowElements; + }, + }, + actions: { + setWfDataName(id, name) { + this.flowWfData.forEach((element: any) => { + if (element.id == id && name) { + element.name = name; + } + }); + }, + setElments(data) { + this.flowElements = data; + }, + // 获取单个节点的数据 + getWfDataNode(id) { + var currentIndex = (this.flowWfData || []).findIndex((element) => element.id === id); + if (currentIndex == -1) { + return null; + } else { + return this.flowWfData[currentIndex]; + } + }, + // 添加单个节点的数据 + setWfDataNode(data) { + let flowWfData = this.flowWfData; + var currentIndex = (flowWfData || []).findIndex((element) => element.id === data.id); + if (currentIndex == -1) { + this.flowWfData.push(data); + } + }, + // 全覆盖,供更新和详情使用 + setWfDataAll(list) { + this.flowWfData = list; + }, + // 修改单个节点的某项数据 + updataWfDataNode(id, key, value) { + let flowWfData = this.flowWfData; + var currentIndex = (flowWfData || []).findIndex((element) => element.id === id); + this.flowWfData[currentIndex][key] = value; + }, + deleteWfData(data) { + let flowWfData = this.flowWfData; + var currentIndex = (flowWfData || []).findIndex((element) => element.id === data.id); + this.flowWfData.splice(currentIndex, 1); + }, + }, +}); diff --git a/src/store/modules/formCall.ts b/src/store/modules/formCall.ts new file mode 100644 index 0000000..24df542 --- /dev/null +++ b/src/store/modules/formCall.ts @@ -0,0 +1,28 @@ +import { defineStore } from 'pinia'; +import { ref } from 'vue' +import { getDictionary } from '@/api/sys/categories'; + +export const useFormCallStore = defineStore('formCall', () => { + const dictionary = ref({}) + async function getDictionaryOptions(code){ + if(Object.keys(dictionary.value).includes(code)){ + return dictionary.value[code] + }else{ + let params = { code } + let res = await getDictionary(params) + let data: any[] = [] + res.forEach(item => { + data.push({ + value: item.itemValue, + label: item.itemName, + }) + }) + dictionary.value[code] = data + return data + } + } + function clearData () { + dictionary.value = {} + } + return { dictionary, getDictionaryOptions, clearData } +}) \ No newline at end of file diff --git a/src/store/modules/formFileUrl.ts b/src/store/modules/formFileUrl.ts new file mode 100644 index 0000000..bf8dd56 --- /dev/null +++ b/src/store/modules/formFileUrl.ts @@ -0,0 +1,57 @@ +import type { + ProjectConfig, + HeaderSetting, + MenuSetting, + TransitionSetting, + MultiTabsSetting, + } from '#/config'; + import type { BeforeMiniState, ApiAddress } from '#/store'; + + import { defineStore } from 'pinia'; + import { store } from '@/store'; + + import { resetRouter } from '@/router'; + import { deepMerge } from '@/utils'; + + interface FormFile { + url:String; + urlList:Array; + } + + export const userFormFileStore = defineStore({ + id: 'formfileurl', + state: (): FormFile => ({ + url:"", + urlList:[] + }), + getters: { + getUrl(state): boolean { + return state.url; + }, + getUrlList(state):boolean{ + return state.urlList; + } + }, + actions: { + setUrl(url:string): void { + this.url = url; + }, + setUrlList(urlList:Array):void{ + this.urlList = urlList; + } + }, + mutations:{ + setUrl(url:string): void { + this.url = url; + }, + setUrlList(urlList:Array):void{ + this.urlList = urlList; + } + } + }); + + // Need to be used outside the setup + export function useAppStoreWithOut() { + return userFormFileStore(store); + } + \ No newline at end of file diff --git a/src/store/modules/locale.ts b/src/store/modules/locale.ts new file mode 100644 index 0000000..176c8f4 --- /dev/null +++ b/src/store/modules/locale.ts @@ -0,0 +1,55 @@ +import type { LocaleSetting, LocaleType } from '#/config'; + +import { defineStore } from 'pinia'; +import { store } from '@/store'; + +import { LOCALE_KEY } from '@/enums/cacheEnum'; +import { createLocalStorage } from '@/utils/cache'; +import { localeSetting } from '@/settings/localeSetting'; + +const ls = createLocalStorage(); + +const lsLocaleSetting = (ls.get(LOCALE_KEY) || localeSetting) as LocaleSetting; + +interface LocaleState { + localInfo: LocaleSetting; +} + +export const useLocaleStore = defineStore({ + id: 'app-locale', + state: (): LocaleState => ({ + localInfo: lsLocaleSetting, + }), + getters: { + getShowPicker(state): boolean { + return !!state.localInfo?.showPicker; + }, + getLocale(state): LocaleType { + return state.localInfo?.locale ?? 'zh_CN'; + }, + }, + actions: { + /** + * Set up multilingual information and cache + * @param info multilingual info + */ + setLocaleInfo(info: Partial) { + this.localInfo = { ...this.localInfo, ...info }; + ls.set(LOCALE_KEY, this.localInfo); + }, + /** + * Initialize multilingual information and load the existing configuration from the local cache + */ + initLocale() { + this.setLocaleInfo({ + ...localeSetting, + ...this.localInfo, + }); + }, + }, +}); + +// Need to be used outside the setup +export function useLocaleStoreWithOut() { + return useLocaleStore(store); +} diff --git a/src/store/modules/lock.ts b/src/store/modules/lock.ts new file mode 100644 index 0000000..efb1e20 --- /dev/null +++ b/src/store/modules/lock.ts @@ -0,0 +1,59 @@ +import type { LockInfo } from '#/store'; + +import { defineStore } from 'pinia'; + +import { LOCK_INFO_KEY } from '@/enums/cacheEnum'; +import { Persistent } from '@/utils/cache/persistent'; +import { useUserStore } from './user'; + +interface LockState { + lockInfo: Nullable; +} + +export const useLockStore = defineStore({ + id: 'app-lock', + state: (): LockState => ({ + lockInfo: Persistent.getLocal(LOCK_INFO_KEY), + }), + getters: { + getLockInfo(state): Nullable { + return state.lockInfo; + }, + }, + actions: { + setLockInfo(info: LockInfo) { + this.lockInfo = Object.assign({}, this.lockInfo, info); + Persistent.setLocal(LOCK_INFO_KEY, this.lockInfo, true); + }, + resetLockInfo() { + Persistent.removeLocal(LOCK_INFO_KEY, true); + this.lockInfo = null; + }, + // Unlock + async unLock(password?: string) { + const userStore = useUserStore(); + if (this.lockInfo?.pwd === password) { + this.resetLockInfo(); + return true; + } + const tryLogin = async () => { + try { + const username = userStore.getUserInfo?.username; + const res = await userStore.login({ + username, + password: password!, + goHome: false, + mode: 'none', + }); + if (res) { + this.resetLockInfo(); + } + return res; + } catch (error) { + return false; + } + }; + return await tryLogin(); + }, + }, +}); diff --git a/src/store/modules/multipleTab.ts b/src/store/modules/multipleTab.ts new file mode 100644 index 0000000..c84ad96 --- /dev/null +++ b/src/store/modules/multipleTab.ts @@ -0,0 +1,361 @@ +import type { RouteLocationNormalized, RouteLocationRaw, Router } from 'vue-router'; + +import { toRaw, unref } from 'vue'; +import { defineStore } from 'pinia'; +import { store } from '@/store'; + +import { useGo, useRedo } from '@/hooks/web/usePage'; +import { Persistent } from '@/utils/cache/persistent'; + +import { PageEnum } from '@/enums/pageEnum'; +import { PAGE_NOT_FOUND_ROUTE, REDIRECT_ROUTE } from '@/router/routes/basic'; +import { getRawRoute } from '@/utils'; +import { MULTIPLE_TABS_KEY } from '@/enums/cacheEnum'; + +import projectSetting from '@/settings/projectSetting'; +import { useUserStore } from '@/store/modules/user'; + +export interface MultipleTabState { + cacheTabList: Set; + tabList: RouteLocationNormalized[]; + lastDragEndIndex: number; +} + +function handleGotoPage(router: Router) { + const go = useGo(router); + go(unref(router.currentRoute).fullPath, true); +} + +const getToTarget = (tabItem: RouteLocationNormalized) => { + const { params, path, query } = tabItem; + return { + params: params || {}, + path, + query: query || {}, + }; +}; + +const cacheTab = projectSetting.multiTabsSetting.cache; + +export const useMultipleTabStore = defineStore({ + id: 'app-multiple-tab', + state: (): MultipleTabState => ({ + // Tabs that need to be cached + cacheTabList: new Set(), + // multiple tab list + tabList: cacheTab ? Persistent.getLocal(MULTIPLE_TABS_KEY) || [] : [], + // Index of the last moved tab + lastDragEndIndex: 0, + }), + getters: { + getTabList(state): RouteLocationNormalized[] { + return state.tabList; + }, + getCachedTabList(state): string[] { + return Array.from(state.cacheTabList); + }, + getLastDragEndIndex(state): number { + return state.lastDragEndIndex; + }, + }, + actions: { + /** + * Update the cache according to the currently opened tabs + */ + async updateCacheTab() { + const cacheMap: Set = new Set(); + + for (const tab of this.tabList) { + const item = getRawRoute(tab); + // Ignore the cache + const needCache = !item.meta?.ignoreKeepAlive; + if (!needCache) { + continue; + } + const name = item.name as string; + cacheMap.add(name); + } + this.cacheTabList = cacheMap; + }, + + /** + * Refresh tabs + */ + async refreshPage(router: Router) { + const { currentRoute } = router; + const route = unref(currentRoute); + const name = route.name; + + const findTab = this.getCachedTabList.find((item) => item === name); + if (findTab) { + this.cacheTabList.delete(findTab); + } + const redo = useRedo(router); + await redo(); + }, + clearCacheTabs(): void { + this.cacheTabList = new Set(); + }, + resetState(): void { + this.tabList = []; + this.clearCacheTabs(); + }, + goToPage(router: Router) { + const go = useGo(router); + const len = this.tabList.length; + const { path } = unref(router.currentRoute); + + let toPath: PageEnum | string = PageEnum.BASE_HOME; + + if (len > 0) { + const page = this.tabList[len - 1]; + const p = page.fullPath || page.path; + if (p) { + toPath = p; + } + } + // Jump to the current page and report an error + path !== toPath && go(toPath as PageEnum, true); + }, + + async addTab(route: RouteLocationNormalized) { + const { path, name, fullPath, params, query, meta } = getRawRoute(route); + // 404 The page does not need to add a tab + if ( + path === PageEnum.ERROR_PAGE || + path === PageEnum.BASE_LOGIN || + !name || + [REDIRECT_ROUTE.name, PAGE_NOT_FOUND_ROUTE.name].includes(name as string) + ) { + return; + } + + let updateIndex = -1; + // Existing pages, do not add tabs repeatedly + const tabHasExits = this.tabList.some((tab, index) => { + updateIndex = index; + return (tab.fullPath || tab.path) === (fullPath || path); + }); + + // If the tab already exists, perform the update operation + if (tabHasExits) { + const curTab = toRaw(this.tabList)[updateIndex]; + if (!curTab) { + return; + } + curTab.params = params || curTab.params; + curTab.query = query || curTab.query; + curTab.fullPath = fullPath || curTab.fullPath; + this.tabList.splice(updateIndex, 1, curTab); + } else { + // Add tab + // 获取动态路由打开数,超过 0 即代表需要控制打开数 + const dynamicLevel = meta?.dynamicLevel ?? -1; + if (dynamicLevel > 0) { + // 如果动态路由层级大于 0 了,那么就要限制该路由的打开数限制了 + // 首先获取到真实的路由,使用配置方式减少计算开销. + // const realName: string = path.match(/(\S*)\//)![1]; + const realPath = meta?.realPath ?? ''; + // 获取到已经打开的动态路由数, 判断是否大于某一个值 + if ( + this.tabList.filter((e) => e.meta?.realPath ?? '' === realPath).length >= dynamicLevel + ) { + // 关闭第一个 + const index = this.tabList.findIndex((item) => item.meta.realPath === realPath); + index !== -1 && this.tabList.splice(index, 1); + } + } + this.tabList.push(route); + } + this.updateCacheTab(); + cacheTab && Persistent.setLocal(MULTIPLE_TABS_KEY, this.tabList); + }, + + async closeTab(tab: RouteLocationNormalized, router: Router) { + const close = (route: RouteLocationNormalized) => { + const { fullPath, meta: { affix } = {} } = route; + if (affix) { + return; + } + const index = this.tabList.findIndex((item) => item.fullPath === fullPath); + index !== -1 && this.tabList.splice(index, 1); + }; + + const { currentRoute, replace } = router; + + const { path } = unref(currentRoute); + if (path !== tab.path) { + // Closed is not the activation tab + close(tab); + this.updateCacheTab(); + return; + } + + // Closed is activated atb + let toTarget: RouteLocationRaw = {}; + + const index = this.tabList.findIndex((item) => item.path === path); + + // If the current is the leftmost tab + if (index === 0) { + // There is only one tab, then jump to the homepage, otherwise jump to the right tab + if (this.tabList.length === 1) { + const userStore = useUserStore(); + toTarget = userStore.getUserInfo.homePath || PageEnum.BASE_HOME; + } else { + // Jump to the right tab + const page = this.tabList[index + 1]; + toTarget = getToTarget(page); + } + } else { + // Close the current tab + const page = this.tabList[index - 1]; + toTarget = getToTarget(page); + } + close(currentRoute.value); + await replace(toTarget); + }, + + // Close according to key + async closeTabByKey(key: string, router: Router) { + const index = this.tabList.findIndex((item) => (item.fullPath || item.path) === key); + if (index !== -1) { + await this.closeTab(this.tabList[index], router); + const { currentRoute, replace } = router; + // 检查当前路由是否存在于tabList中 + const isActivated = this.tabList.findIndex((item) => { + return item.fullPath === currentRoute.value.fullPath; + }); + // 如果当前路由不存在于TabList中,尝试切换到其它路由 + if (isActivated === -1) { + let pageIndex; + if (index > 0) { + pageIndex = index - 1; + } else if (index < this.tabList.length - 1) { + pageIndex = index + 1; + } else { + pageIndex = -1; + } + if (pageIndex >= 0) { + const page = this.tabList[index - 1]; + const toTarget = getToTarget(page); + await replace(toTarget); + } + } + } + }, + + // Sort the tabs + async sortTabs(oldIndex: number, newIndex: number) { + const currentTab = this.tabList[oldIndex]; + this.tabList.splice(oldIndex, 1); + this.tabList.splice(newIndex, 0, currentTab); + this.lastDragEndIndex = this.lastDragEndIndex + 1; + }, + + // Close the tab on the right and jump + async closeLeftTabs(route: RouteLocationNormalized, router: Router) { + const index = this.tabList.findIndex((item) => item.path === route.path); + + if (index > 0) { + const leftTabs = this.tabList.slice(0, index); + const pathList: string[] = []; + for (const item of leftTabs) { + const affix = item?.meta?.affix ?? false; + if (!affix) { + pathList.push(item.fullPath); + } + } + this.bulkCloseTabs(pathList); + } + this.updateCacheTab(); + handleGotoPage(router); + }, + + // Close the tab on the left and jump + async closeRightTabs(route: RouteLocationNormalized, router: Router) { + const index = this.tabList.findIndex((item) => item.fullPath === route.fullPath); + + if (index >= 0 && index < this.tabList.length - 1) { + const rightTabs = this.tabList.slice(index + 1, this.tabList.length); + + const pathList: string[] = []; + for (const item of rightTabs) { + const affix = item?.meta?.affix ?? false; + if (!affix) { + pathList.push(item.fullPath); + } + } + this.bulkCloseTabs(pathList); + } + this.updateCacheTab(); + handleGotoPage(router); + }, + + async closeAllTab(router: Router) { + this.tabList = this.tabList.filter((item) => item?.meta?.affix ?? false); + this.clearCacheTabs(); + this.goToPage(router); + }, + + /** + * Close other tabs + */ + async closeOtherTabs(route: RouteLocationNormalized, router: Router) { + const closePathList = this.tabList.map((item) => item.fullPath); + + const pathList: string[] = []; + + for (const path of closePathList) { + if (path !== route.fullPath) { + const closeItem = this.tabList.find((item) => item.fullPath === path); + if (!closeItem) { + continue; + } + const affix = closeItem?.meta?.affix ?? false; + if (!affix) { + pathList.push(closeItem.fullPath); + } + } + } + this.bulkCloseTabs(pathList); + this.updateCacheTab(); + Persistent.setLocal(MULTIPLE_TABS_KEY, this.tabList, true); + handleGotoPage(router); + }, + + /** + * Close tabs in bulk + */ + async bulkCloseTabs(pathList: string[]) { + this.tabList = this.tabList.filter((item) => !pathList.includes(item.fullPath)); + }, + + /** + * Set tab's title + */ + async setTabTitle(title: string, route: RouteLocationNormalized) { + const findTab = this.getTabList.find((item) => item === route); + if (findTab) { + findTab.meta.title = title; + await this.updateCacheTab(); + } + }, + /** + * replace tab's path + * **/ + async updateTabPath(fullPath: string, route: RouteLocationNormalized) { + const findTab = this.getTabList.find((item) => item === route); + if (findTab) { + findTab.fullPath = fullPath; + findTab.path = fullPath; + await this.updateCacheTab(); + } + }, + }, +}); + +// Need to be used outside the setup +export function useMultipleTabWithOutStore() { + return useMultipleTabStore(store); +} diff --git a/src/store/modules/onlineFormDesign.ts b/src/store/modules/onlineFormDesign.ts new file mode 100644 index 0000000..37a9f98 --- /dev/null +++ b/src/store/modules/onlineFormDesign.ts @@ -0,0 +1,67 @@ +import { defineStore } from 'pinia'; +import { getDictionaryType, getDictionary } from '@/api/sys/categories.ts' +import { ref } from 'vue' + +export const useOnlineFormDesignStore = defineStore('onlineFormDesign', () => { + const selectOptions = ref({}) + const selectDictionaryData = ref([]) + const timeout = ref() + function setSelectOptions(key, code){ + let params = { code } + getDictionary(params).then(res => { + let data: any[] = [] + res.forEach(item => { + data.push({ + value: item.itemValue, + label: item.itemName, + }) + }) + selectOptions.value[key] = data + }).catch(error => { + console.log(error) + }) + } + function getSelectOption(key){ + return selectOptions.value[key]? selectOptions.value[key] : [] + } + function setSelectDictionaryData (dataList) { + selectDictionaryData.value = dataList + } + function getSelectDictionaryData() { + return selectDictionaryData.value + } + function getSelectData(value: string) { + if (timeout.value) { + clearTimeout(timeout.value); + timeout.value = null; + } + function fake() { + getDictionaryType() + .then(res => { + let data: any[] = []; + res.forEach(item => { + data.push({ + value: item.itemCode, + label: item.itemName, + }) + }) + if(value !== ""){ + data = data.filter(item => { + return item.label.indexOf(value) > -1 + }) + } + setSelectDictionaryData(data) + }); + } + timeout.value = setTimeout(fake, 300); + } + return { + selectOptions, + selectDictionaryData, + setSelectOptions, + getSelectOption, + setSelectDictionaryData, + getSelectDictionaryData, + getSelectData, + } +}) \ No newline at end of file diff --git a/src/store/modules/permission.ts b/src/store/modules/permission.ts new file mode 100644 index 0000000..c5bcefa --- /dev/null +++ b/src/store/modules/permission.ts @@ -0,0 +1,469 @@ +import type { AppRouteRecordRaw, Menu } from '@/router/types'; + +import { defineStore } from 'pinia'; +import { store } from '@/store'; +import { useI18n } from '@/hooks/web/useI18n'; +import { useUserStore } from './user'; +import { useAppStoreWithOut } from './app'; +import { toRaw } from 'vue'; +import { transformObjToRoute, flatMultiLevelRoutes } from '@/router/helper/routeHelper'; +import { transformRouteToMenu } from '@/router/helper/menuHelper'; + +import projectSetting from '@/settings/projectSetting'; + +import { PermissionModeEnum } from '@/enums/appEnum'; + +import { asyncRoutes } from '@/router/routes'; +import { ERROR_LOG_ROUTE, PAGE_NOT_FOUND_ROUTE } from '@/router/routes/basic'; + +import { filter, forEach } from '@/utils/helper/treeHelper'; + +import { getMenuList } from '@/api/sys/menu'; +import { getPermCode } from '@/api/sys/user'; + +import { useMessage } from '@/hooks/web/useMessage'; +import { PageEnum } from '@/enums/pageEnum'; + +import { router } from '@/router'; +import { LAYOUT } from '@/router/constant'; +import dayjs from 'dayjs'; + +interface PermissionState { + // Permission code list + // 权限代码列表 + permCodeList: string[] | number[]; + // Whether the route has been dynamically added + // 路由是否动态添加 + isDynamicAddedRoute: boolean; + // To trigger a menu update + // 触发菜单更新 + lastBuildMenuTime: number; + // Backstage menu list + // 后台菜单列表 + backMenuList: Menu[]; + // 菜单列表 + frontMenuList: Menu[]; + changeMenu: number; +} + +export const usePermissionStore = defineStore({ + id: 'app-permission', + state: (): PermissionState => ({ + // 权限代码列表 + permCodeList: [], + // Whether the route has been dynamically added + // 路由是否动态添加 + isDynamicAddedRoute: false, + // To trigger a menu update + // 触发菜单更新 + lastBuildMenuTime: 0, + // Backstage menu list + // 后台菜单列表 + backMenuList: [], + // menu List + // 菜单列表 + frontMenuList: [], + changeMenu: dayjs().valueOf(), + }), + getters: { + getChangeMenu(state): number { + return state.changeMenu; + }, + getPermCodeList(state): string[] | number[] { + return state.permCodeList; + }, + getBackMenuList(state): Menu[] { + return state.backMenuList; + }, + getFrontMenuList(state): Menu[] { + return state.frontMenuList; + }, + getLastBuildMenuTime(state): number { + return state.lastBuildMenuTime; + }, + getIsDynamicAddedRoute(state): boolean { + return state.isDynamicAddedRoute; + }, + }, + actions: { + setPermCodeList(codeList: string[]) { + this.permCodeList = codeList; + }, + + setBackMenuList(list: Menu[]) { + this.backMenuList = list; + list?.length > 0 && this.setLastBuildMenuTime(); + }, + + setChangeMenu() { + this.changeMenu = dayjs().valueOf(); + }, + + setFrontMenuList(list: Menu[]) { + this.frontMenuList = list; + }, + + setLastBuildMenuTime() { + this.lastBuildMenuTime = new Date().getTime(); + }, + + setDynamicAddedRoute(added: boolean) { + this.isDynamicAddedRoute = added; + }, + resetState(): void { + this.isDynamicAddedRoute = false; + this.permCodeList = []; + this.backMenuList = []; + this.lastBuildMenuTime = 0; + }, + async changePermissionCode() { + const codeList = await getPermCode(); + this.setPermCodeList(codeList); + }, + + // 构建路由 + async buildRoutesAction(): Promise { + const { t } = useI18n(); + const userStore = useUserStore(); + const appStore = useAppStoreWithOut(); + + let routes: AppRouteRecordRaw[] = []; + const roleList = toRaw(userStore.getRoleList) || []; + const { permissionMode = projectSetting.permissionMode } = appStore.getProjectConfig; + + const normalizeMenu = (data) => { + let path = ''; + if (data.url.indexOf('@') > 0) { + path = data.url.replace('@', '/'); + } else { + path = + data.url || '/formCallPage?id=' + data.id + '&name=' + data.name + '&code=' + data.code; + } + const newPath = { + orderNo: data.sortNo, + icon: data.iconName, + title: data.name, + meta: { + orderNo: data.sortNo, + icon: data.iconName, + title: data.name, + elements: (data && data.elements) || '', + }, + name: data.name, + hideMenu: data.status == 1 ? false : true, + path: path, + id: data.id || '', + children: [], + }; + if (data.children && data.children.length > 0) { + data.children.forEach((element) => { + newPath.children.push(normalizeMenu(element)); + }); + } + return newPath; + }; + const childRoute = (childData) => { + const modules = import.meta.glob('../../views/**/**/**/index.vue'); + childData.forEach((element) => { + // 菜单里配置带参数,但没有单独的主路由,先注册主路由 + if (element.status == 1 && element.url.indexOf('@') > 0) { + if (router.hasRoute(element.code)) { + const path = element.url.substring(0, element.url.indexOf('@')); + router.addRoute(element.code, { + path: path + '/:id', + name: element.url.replaceAll('/', ''), + meta: { + title: element.name, + icon: element.iconName, + elements: element.elements, + }, + component: modules['../../views/demo' + path + '/index.vue'], + }); + } else { + const path = element.url.substring(0, element.url.indexOf('@')); + router.addRoute('Root', { + path: path, + name: element.code, + meta: { + title: element.name, + icon: element.iconName, + hideChildrenInMenu: true, + elements: element.elements, + }, + component: LAYOUT, + children: [ + { + path: path + '/:id', + name: element.url.replaceAll('/', ''), + meta: { + title: element.name, + icon: element.iconName, + elements: element.elements, + }, + component: modules['../../views/demo' + path + '/index.vue'], + }, + ], + }); + } + } else if (element.code && element.status == 1) { + router.addRoute(element.code, { + path: element.url, + name: element.url.replaceAll('/', ''), + meta: { + title: element.name, + icon: element.iconName, + elements: element.elements, + }, + // component: () => import('../../views/demo' + element.url + '/index.vue') + component: modules['../../views/demo' + element.url + '/index.vue'], + }); + } + if (element.children && element.children.length > 0) { + childRoute(element.children); + } + }); + }; + // 注册路由 + const registeredRoute = (data) => { + const modules = import.meta.glob('../../views/**/**/**/index.vue'); + if (data.url.split('/')[1] == 'map') { + // 大屏的情况下不继承layout + router.addRoute('Root', { + path: data.url, + name: data.code, + meta: { + title: data.name, + icon: data.iconName, + elements: data.elements, + }, + component: modules['../../views' + data.url + '/index.vue'], + }); + } else { + // 正常菜单 + if (data.children.length == 0 && data.status == 1) { + // 没有子菜单 + if (data.url.indexOf('@') > 0) { + //给带参数的路由先注册主路由 + const path = data.url.substring(0, data.url.indexOf('@')); + router.addRoute('Root', { + path: path, + name: data.code, + meta: { + title: data.name, + icon: data.iconName, + hideChildrenInMenu: true, + elements: data.elements, + }, + component: LAYOUT, + children: [ + { + path: path + '/:id', + name: data.url.replaceAll('/', ''), + meta: { + title: data.name, + icon: data.iconName, + elements: data.elements, + }, + component: modules['../../views/demo' + path + '/index.vue'], + }, + ], + }); + } else { + router.addRoute('Root', { + path: data.url, + name: data.code, + meta: { + title: data.name, + icon: data.iconName, + hideChildrenInMenu: true, + elements: data.elements, + }, + component: LAYOUT, + children: [ + { + path: data.url, + name: data.url.replaceAll('/', ''), + meta: { + title: data.name, + icon: data.iconName, + elements: data.elements, + }, + component: modules['../../views/demo' + data.url + '/index.vue'], + }, + ], + }); + } + } else { + // 有子菜单 + if (data.status == 0) { + return; + } + router.addRoute('Root', { + path: data.url, + name: data.code, + meta: { + title: data.name, + icon: data.iconName, + elements: data.elements, + }, + component: + data.parentId == 0 ? LAYOUT : modules['../../views/demo' + data.url + '/index.vue'], + }); + if (data.children && data.children.length > 0) { + childRoute(data.children); + } + } + } + // console.log(router.getRoutes()); + }; + + //通过后端获取菜单 + const _this = this; + async function buildMenusByServer(list) { + const data = await getMenuList({ typeId: userStore.getSubject }); + const moduleRoutes = list; + await data.forEach((value) => { + moduleRoutes.push(normalizeMenu(value)); + registeredRoute(value); + }); + await Promise.all(moduleRoutes); + // 设置菜单列表 + _this.setFrontMenuList(moduleRoutes); + } + + // 路由过滤器 在 函数filter 作为回调传入遍历使用 + const routeFilter = (route: AppRouteRecordRaw) => { + const { meta } = route; + // 抽出角色 + const { roles } = meta || {}; + if (!roles) return true; + // 进行角色权限判断 + return roleList.some((role) => roles.includes(role)); + }; + + const routeRemoveIgnoreFilter = (route: AppRouteRecordRaw) => { + const { meta } = route; + // ignoreRoute 为true 则路由仅用于菜单生成,不会在实际的路由表中出现 + const { ignoreRoute } = meta || {}; + // arr.filter 返回 true 表示该元素通过测试 + return !ignoreRoute; + }; + + /** + * @description 根据设置的首页path,修正routes中的affix标记(固定首页) + * */ + const patchHomeAffix = (routes: AppRouteRecordRaw[]) => { + if (!routes || routes.length === 0) return; + let homePath: string = userStore.getUserInfo.homePath || PageEnum.BASE_HOME; + + function patcher(routes: AppRouteRecordRaw[], parentPath = '') { + if (parentPath) parentPath = parentPath + '/'; + routes.forEach((route: AppRouteRecordRaw) => { + const { path, children, redirect } = route; + const currentPath = path.startsWith('/') ? path : parentPath + path; + if (currentPath === homePath) { + if (redirect) { + homePath = route.redirect! as string; + } else { + route.meta = Object.assign({}, route.meta, { affix: true }); + throw new Error('end'); + } + } + children && children.length > 0 && patcher(children, currentPath); + }); + } + + try { + patcher(routes); + } catch (e) { + // 已处理完毕跳出循环 + } + return; + }; + switch (permissionMode) { + // 角色权限 + case PermissionModeEnum.ROLE: + // 对非一级路由进行过滤 + routes = filter(asyncRoutes, routeFilter); + // 对一级路由根据角色权限过滤 + routes = routes.filter(routeFilter); + // Convert multi-level routing to level 2 routing + // 将多级路由转换为 2 级路由 + routes = flatMultiLevelRoutes(routes); + break; + + // 路由映射, 默认进入该case + case PermissionModeEnum.ROUTE_MAPPING: + // 对非一级路由进行过滤 + routes = filter(asyncRoutes, routeFilter); + // 对一级路由再次根据角色权限过滤 + routes = routes.filter(routeFilter); + // 将路由转换成菜单 + const menuList = transformRouteToMenu(routes, true); + // 移除掉 ignoreRoute: true 的路由 非一级路由 + routes = filter(routes, routeRemoveIgnoreFilter); + // 移除掉 ignoreRoute: true 的路由 一级路由; + routes = routes.filter(routeRemoveIgnoreFilter); + // 对菜单进行排序 + menuList.sort((a, b) => { + return (a.meta?.orderNo || 0) - (b.meta?.orderNo || 0); + }); + // await buildMenusByServer(menuList); + + // Convert multi-level routing to level 2 routing + // 将多级路由转换为 2 级路由 + routes = flatMultiLevelRoutes(routes); + break; + + // If you are sure that you do not need to do background dynamic permissions, please comment the entire judgment below + // 如果确定不需要做后台动态权限,请在下方注释整个判断 + case PermissionModeEnum.BACK: + const { createMessage } = useMessage(); + + createMessage.loading({ + content: t('sys.app.menuLoading'), + duration: 1, + }); + + // !Simulate to obtain permission codes from the background, + // 模拟从后台获取权限码, + // this function may only need to be executed once, and the actual project can be put at the right time by itself + // 这个功能可能只需要执行一次,实际项目可以自己放在合适的时间 + let routeList: AppRouteRecordRaw[] = []; + try { + await this.changePermissionCode(); + routeList = (await getMenuList()) as AppRouteRecordRaw[]; + } catch (error) { + console.error(error); + } + // Dynamically introduce components + // 动态引入组件 + routeList = transformObjToRoute(routeList); + + // Background routing to menu structure + // 后台路由到菜单结构 + const backMenuList = transformRouteToMenu(routeList); + this.setBackMenuList(backMenuList); + + // remove meta.ignoreRoute item + // 删除 meta.ignoreRoute 项 + routeList = filter(routeList, routeRemoveIgnoreFilter); + routeList = routeList.filter(routeRemoveIgnoreFilter); + + routeList = flatMultiLevelRoutes(routeList); + routes = [PAGE_NOT_FOUND_ROUTE, ...routeList]; + break; + } + + routes.push(ERROR_LOG_ROUTE); + patchHomeAffix(routes); + return routes; + }, + }, +}); + +// Need to be used outside the setup +// 需要在设置之外使用 +export function usePermissionStoreWithOut() { + return usePermissionStore(store); +} diff --git a/src/store/modules/subTable.ts b/src/store/modules/subTable.ts new file mode 100644 index 0000000..7b8a334 --- /dev/null +++ b/src/store/modules/subTable.ts @@ -0,0 +1,66 @@ +import { defineStore } from 'pinia'; + +export const subTableStore = defineStore({ + id: 'subTable', + state: () => ({ + tableDta: [], + groupData: {}, + oldDefaultGroupData: {}, + toSetGroupData: false, + }), + getters: { + getTableData(state) { + return state.tableDta; + }, + getGroupData(state) { + return state.groupData; + }, + getOldDefaultGroupData(state) { + return state.oldDefaultGroupData; + }, + getToSetGroupData(state){ + return state.toSetGroupData; + } + }, + actions: { + setTableData(data) { + this.tableDta = data; + }, + setToSetGroupData(){ + this.toSetGroupData = true + }, + setSingleData(parentFileId, data) { + this.tableDta.forEach((item, i) => { + if (item.parentFileId == parentFileId) { + item.child = data; + } + }); + }, + setGroupData(data) { + for (const key2 in data) { + if (data[key2] != undefined) { + this.groupData[key2] = data[key2]; + } + } + }, + setOldDefaultGroupData(data) { + for (const key2 in data) { + if (data[key2] != undefined) { + this.oldDefaultGroupData[key2] = data[key2]; + } + } + }, + setOneGroupData (key,data){ + this.groupData[key] = data + }, + clearGoupData() { + this.groupData = {}; + this.toSetGroupData = false; + }, + clearGroupDataKeyList(keyList){ + keyList.forEach(key => { + this.groupData[key] = "" + }) + } + }, +}); diff --git a/src/store/modules/tableSetting.ts b/src/store/modules/tableSetting.ts new file mode 100644 index 0000000..b6055af --- /dev/null +++ b/src/store/modules/tableSetting.ts @@ -0,0 +1,109 @@ +import { defineStore } from 'pinia'; + +import { TABLE_SETTING_KEY } from '@/enums/cacheEnum'; + +import { Persistent } from '@/utils/cache/persistent'; + +import type { TableSetting } from '#/store'; +import type { SizeType, ColumnOptionsType } from '@/components/Table/src/types/table'; + +interface TableSettingState { + setting: Nullable>; +} + +export const useTableSettingStore = defineStore({ + id: 'table-setting', + state: (): TableSettingState => ({ + setting: Persistent.getLocal(TABLE_SETTING_KEY), + }), + getters: { + getTableSetting(state): Nullable> { + return state.setting; + }, + // + getTableSize(state) { + return state.setting?.size || 'middle'; + }, + // + getShowIndexColumn(state) { + return (routerName: string) => { + return state.setting?.showIndexColumn?.[routerName]; + }; + }, + // + getShowRowSelection(state) { + return (routerName: string) => { + return state.setting?.showRowSelection?.[routerName]; + }; + }, + // + getColumns(state) { + return (routerName: string) => { + return state.setting?.columns && state.setting?.columns[routerName] + ? state.setting?.columns[routerName] + : null; + }; + }, + }, + actions: { + setTableSetting(setting: Partial) { + this.setting = Object.assign({}, this.setting, setting); + Persistent.setLocal(TABLE_SETTING_KEY, this.setting, true); + }, + resetTableSetting() { + Persistent.removeLocal(TABLE_SETTING_KEY, true); + this.setting = null; + }, + // + setTableSize(size: SizeType) { + this.setTableSetting( + Object.assign({}, this.setting, { + size, + }), + ); + }, + // + setShowIndexColumn(routerName: string, show: boolean) { + this.setTableSetting( + Object.assign({}, this.setting, { + showIndexColumn: { + ...this.setting?.showIndexColumn, + [routerName]: show, + }, + }), + ); + }, + // + setShowRowSelection(routerName: string, show: boolean) { + this.setTableSetting( + Object.assign({}, this.setting, { + showRowSelection: { + ...this.setting?.showRowSelection, + [routerName]: show, + }, + }), + ); + }, + // + setColumns(routerName: string, columns: Array) { + this.setTableSetting( + Object.assign({}, this.setting, { + columns: { + ...this.setting?.columns, + [routerName]: columns, + }, + }), + ); + }, + clearColumns(routerName: string) { + this.setTableSetting( + Object.assign({}, this.setting, { + columns: { + ...this.setting?.columns, + [routerName]: undefined, + }, + }), + ); + }, + }, +}); diff --git a/src/store/modules/user.ts b/src/store/modules/user.ts new file mode 100644 index 0000000..618fe53 --- /dev/null +++ b/src/store/modules/user.ts @@ -0,0 +1,224 @@ +import type { UserInfo } from '#/store'; +import type { ErrorMessageMode } from '#/axios'; +import { defineStore } from 'pinia'; +import { store } from '@/store'; +import { RoleEnum } from '@/enums/roleEnum'; +import { PageEnum } from '@/enums/pageEnum'; +import { + ROLES_KEY, + TOKEN_KEY, + USER_INFO_KEY, + SUBJECT_KEY, + SUBJECT_TITLE, + SUBJECT_LOGO_TITLE, +} from '@/enums/cacheEnum'; +import { getAuthCache, setAuthCache } from '@/utils/auth'; +import { GetUserInfoModel, LoginParams } from '@/api/sys/model/userModel'; +import { doLogout, getUserInfo, loginApi } from '@/api/sys/user'; +import { useI18n } from '@/hooks/web/useI18n'; +import { useMessage } from '@/hooks/web/useMessage'; +import { router } from '@/router'; +import { usePermissionStore } from '@/store/modules/permission'; +import { RouteRecordRaw } from 'vue-router'; +import { PAGE_NOT_FOUND_ROUTE } from '@/router/routes/basic'; +import { isArray } from '@/utils/is'; +import { h } from 'vue'; +import md5 from 'js-md5'; +import { useMultipleTabStore } from '@/store/modules/multipleTab'; + +interface UserState { + userInfo: Nullable; + token?: string; + roleList: RoleEnum[]; + sessionTimeout?: boolean; + lastUpdateTime: number; + subject?: string; + subjectTitle?: string; + subjectLogoTitle?: string; +} + +export const useUserStore = defineStore({ + id: 'app-user', + state: (): UserState => ({ + // user info + userInfo: null, + // token + token: undefined, + // roleList + roleList: [], + // Whether the login expired + sessionTimeout: false, + // Last fetch time + lastUpdateTime: 0, + subject: '', + subjectTitle: '', + subjectLogoTitle: '', + }), + getters: { + getUserInfo(state): UserInfo { + return state.userInfo || getAuthCache(USER_INFO_KEY) || {}; + }, + getToken(state): string { + return state.token || getAuthCache(TOKEN_KEY); + }, + getRoleList(state): RoleEnum[] { + return state.roleList.length > 0 ? state.roleList : getAuthCache(ROLES_KEY); + }, + getSessionTimeout(state): boolean { + return !!state.sessionTimeout; + }, + getLastUpdateTime(state): number { + return state.lastUpdateTime; + }, + getSubject(state): string { + return state.subject || getAuthCache(SUBJECT_KEY); + }, + getSubjectTitle(state): string { + return state.subjectTitle || getAuthCache(SUBJECT_TITLE); + }, + getSubjectLogoTitle(state): string { + return state.subjectLogoTitle || getAuthCache(SUBJECT_LOGO_TITLE); + }, + }, + actions: { + async setSubject( + subject: string | undefined, + subjectTitle: string | undefined, + logoTitle: string | undefined, + link: string, + ) { + this.subject = subject; + setAuthCache(SUBJECT_KEY, subject); + setAuthCache(SUBJECT_TITLE, subjectTitle); + setAuthCache(SUBJECT_LOGO_TITLE, logoTitle); + if (subject != undefined) { + const permissionStore = usePermissionStore(); + await permissionStore.buildRoutesAction(); + const tabStore = useMultipleTabStore(); + tabStore.resetState(); + await router.replace(link); + } + }, + setToken(info: string | undefined) { + this.token = info ? info : ''; // for null or undefined value + //临时设置token给大屏使用 + localStorage.setItem('X-Token', info || ''); + setAuthCache(TOKEN_KEY, info); + }, + setRoleList(roleList: RoleEnum[]) { + this.roleList = roleList; + setAuthCache(ROLES_KEY, roleList); + }, + setUserInfo(info: UserInfo | null) { + this.userInfo = info; + this.lastUpdateTime = new Date().getTime(); + setAuthCache(USER_INFO_KEY, info); + }, + setSessionTimeout(flag: boolean) { + this.sessionTimeout = flag; + }, + resetState() { + this.userInfo = null; + this.token = ''; + this.roleList = []; + this.sessionTimeout = false; + }, + /** + * @description: login + */ + async login( + params: LoginParams & { + goHome?: boolean; + mode?: ErrorMessageMode; + }, + ): Promise { + try { + const { goHome = true, mode, ...loginParams } = params; + loginParams.password = md5(loginParams.password); + const data = await loginApi(loginParams, mode); + const { token } = data; + + // save token + this.setToken(token); + return this.afterLoginAction(goHome); + } catch (error) { + return Promise.reject(error); + } + }, + async afterLoginAction(goHome?: boolean): Promise { + if (!this.getToken) return null; + // get user info + const userInfo = await this.getUserInfoAction(); + + const sessionTimeout = this.sessionTimeout; + if (sessionTimeout) { + this.setSessionTimeout(false); + } else { + const permissionStore = usePermissionStore(); + if (!permissionStore.isDynamicAddedRoute) { + const routes = await permissionStore.buildRoutesAction(); + routes.forEach((route) => { + router.addRoute(route as unknown as RouteRecordRaw); + }); + router.addRoute(PAGE_NOT_FOUND_ROUTE as unknown as RouteRecordRaw); + permissionStore.setDynamicAddedRoute(true); + } + goHome && (await router.replace(userInfo?.homePath || PageEnum.BASE_HOME)); + // goHome && (await router.replace(userInfo?.homePath || PageEnum.SUBJECT_HOME)); + } + return userInfo; + }, + async getUserInfoAction(): Promise { + if (!this.getToken) return null; + const userInfo = await getUserInfo(); + const { roles = [] } = userInfo; + if (isArray(roles)) { + const roleList = roles.map((item) => item.value) as RoleEnum[]; + this.setRoleList(roleList); + } else { + userInfo.roles = []; + this.setRoleList([]); + } + this.setUserInfo(userInfo); + return userInfo; + }, + /** + * @description: logout + */ + async logout(goLogin = false) { + if (this.getToken) { + try { + await doLogout(); + } catch { + console.log('注销Token失败'); + } + } + this.setToken(undefined); + this.setSubject(undefined, undefined, undefined, ''); + this.setSessionTimeout(false); + this.setUserInfo(null); + goLogin && router.push(PageEnum.BASE_LOGIN); + }, + + /** + * @description: Confirm before logging out + */ + confirmLoginOut() { + const { createConfirm } = useMessage(); + const { t } = useI18n(); + createConfirm({ + iconType: 'warning', + title: () => h('span', t('sys.app.logoutTip')), + content: () => h('span', t('sys.app.logoutMessage')), + onOk: async () => { + await this.logout(true); + }, + }); + }, + }, +}); + +// Need to be used outside the setup +export function useUserStoreWithOut() { + return useUserStore(store); +} diff --git a/src/store/plugin/persist.ts b/src/store/plugin/persist.ts new file mode 100644 index 0000000..8c8939f --- /dev/null +++ b/src/store/plugin/persist.ts @@ -0,0 +1,75 @@ +/** + * Pinia Persist Plugin + * Pinia 持久化插件 + * @link https://prazdevs.github.io/pinia-plugin-persistedstate/zh/guide/ + * + */ +import type { Pinia } from 'pinia'; +import { createPersistedState, Serializer } from 'pinia-plugin-persistedstate'; +import type { PersistedStateFactoryOptions } from 'pinia-plugin-persistedstate'; +import { getCommonStoragePrefix } from '@/utils/env'; +import { Encryption, EncryptionFactory } from '@/utils/cipher'; +import { cacheCipher, SHOULD_ENABLE_STORAGE_ENCRYPTION } from '@/settings/encryptionSetting'; + +export const PERSIST_KEY_PREFIX = getCommonStoragePrefix(); + +const persistEncryption: Encryption = EncryptionFactory.createAesEncryption({ + key: cacheCipher.key, + iv: cacheCipher.iv, +}); + +/** + * Custom serializer for serialization and deserialization of storage data + * 自定义序列化器,用于序列化和反序列化存储数据 + * + * @param shouldEnableEncryption whether to enable encryption for storage data 是否启用存储数据加密 + * @returns serializer + */ +function customSerializer(shouldEnableEncryption: boolean): Serializer { + if (shouldEnableEncryption) { + return { + deserialize: (value) => { + const decrypted = persistEncryption.decrypt(value); + return JSON.parse(decrypted); + }, + serialize: (value) => { + const serialized = JSON.stringify(value); + return persistEncryption.encrypt(serialized); + }, + }; + } else { + return { + deserialize: (value) => { + return JSON.parse(value); + }, + serialize: (value) => { + return JSON.stringify(value); + }, + }; + } +} + +/** + * Register Pinia Persist Plugin + * 注册 Pinia 持久化插件 + * + * @param pinia Pinia instance Pinia 实例 + */ +export function registerPiniaPersistPlugin(pinia: Pinia) { + pinia.use(createPersistedState(createPersistedStateOptions(PERSIST_KEY_PREFIX))); +} + +/** + * Create Persisted State Options + * 创建持久化状态选项 + * + * @param keyPrefix prefix for storage key 储存键前缀 + * @returns persisted state factory options + */ +export function createPersistedStateOptions(keyPrefix: string): PersistedStateFactoryOptions { + return { + storage: localStorage, + key: (id) => `${keyPrefix}__${id}`, + serializer: customSerializer(SHOULD_ENABLE_STORAGE_ENCRYPTION), + }; +} diff --git a/src/types/index.d.ts b/src/types/index.d.ts new file mode 100644 index 0000000..c5278cf --- /dev/null +++ b/src/types/index.d.ts @@ -0,0 +1 @@ +declare module "@/../lib/vform/designer.umd.js" \ No newline at end of file diff --git a/src/utils/EpsgTransform.ts b/src/utils/EpsgTransform.ts new file mode 100644 index 0000000..18cb782 --- /dev/null +++ b/src/utils/EpsgTransform.ts @@ -0,0 +1,40 @@ +// 火星坐标系GCJ02转地球坐标系WGS84 +var PI = 3.14159265358979324; +export function transformGCJ2WGS(gcjLat, gcjLon) { + let d = delta(gcjLat, gcjLon) + return { + 'lat': gcjLat - d.lat, + 'lon': gcjLon - d.lon + } + } + + function delta(lat, lon) { + let a = 6378245.0 // a: 卫星椭球坐标投影到平面地图坐标系的投影因子。 + let ee = 0.00669342162296594323 // ee: 椭球的偏心率。 + let dLat = transformLat(lon - 105.0, lat - 35.0) + let dLon = transformLon(lon - 105.0, lat - 35.0) + let radLat = lat / 180.0 * PI + let magic = Math.sin(radLat) + magic = 1 - ee * magic * magic + let sqrtMagic = Math.sqrt(magic) + dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * PI) + dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * PI) + return { + 'lat': dLat, + 'lon': dLon + } + } + function transformLat(x, y) { + let ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * Math.sqrt(Math.abs(x)) + ret += (20.0 * Math.sin(6.0 * x * PI) + 20.0 * Math.sin(2.0 * x * PI)) * 2.0 / 3.0 + ret += (20.0 * Math.sin(y * PI) + 40.0 * Math.sin(y / 3.0 * PI)) * 2.0 / 3.0 + ret += (160.0 * Math.sin(y / 12.0 * PI) + 320 * Math.sin(y * PI / 30.0)) * 2.0 / 3.0 + return ret + } + function transformLon(x, y) { + let ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * Math.sqrt(Math.abs(x)) + ret += (20.0 * Math.sin(6.0 * x * PI) + 20.0 * Math.sin(2.0 * x * PI)) * 2.0 / 3.0 + ret += (20.0 * Math.sin(x * PI) + 40.0 * Math.sin(x / 3.0 * PI)) * 2.0 / 3.0 + ret += (150.0 * Math.sin(x / 12.0 * PI) + 300.0 * Math.sin(x / 30.0 * PI)) * 2.0 / 3.0 + return ret + } \ No newline at end of file diff --git a/src/utils/__test__/index.test.ts b/src/utils/__test__/index.test.ts new file mode 100644 index 0000000..bc6995e --- /dev/null +++ b/src/utils/__test__/index.test.ts @@ -0,0 +1,145 @@ +// 暂时未安装依赖,无法测试 +// @ts-ignore +import { describe, expect, test } from 'vitest'; +import { deepMerge } from '@/utils'; + +describe('deepMerge function', () => { + test('should correctly merge basic data types', () => { + const source = { a: 1, b: 2, c: null }; + const target = { + a: 2, + b: undefined, + c: 3, + }; + const expected = { + a: 2, + b: 2, + c: 3, + }; + expect(deepMerge(source, target)).toStrictEqual(expected); + }); + + test('should return the same date if only 1 is passed', () => { + const foo = new Date(); + const merged = deepMerge(foo, null); + const merged2 = deepMerge(undefined, foo); + expect(merged).toStrictEqual(foo); + expect(merged2).toStrictEqual(foo); + expect(merged).toStrictEqual(merged2); + }); + + test('should merge two objects recursively', () => { + const source = { + a: { b: { c: 1 }, d: [1, 2] }, + e: [1, 2], + foo: { bar: 3 }, + array: [ + { + does: 'work', + too: [1, 2, 3], + }, + ], + r: { a: 1 }, + }; + const target = { + a: { b: { d: [3] } }, + e: [3], + foo: { baz: 4 }, + qu: 5, + array: [ + { + does: 'work', + too: [4, 5, 6], + }, + { + really: 'yes', + }, + ], + r: { a: 2 }, + }; + const expected = { + a: { b: { c: 1, d: [3] }, d: [1, 2] }, + e: [3], + foo: { + bar: 3, + baz: 4, + }, + array: [ + { + does: 'work', + too: [4, 5, 6], + }, + { + really: 'yes', + }, + ], + qu: 5, + r: { a: 2 }, + }; + expect(deepMerge(source, target)).toStrictEqual(expected); + }); + + test('should replace arrays by default', () => { + const source = { + a: { b: { d: [1, 2] } }, + e: [1, 2], + }; + const target = { + a: { b: { d: [3] } }, + e: [3], + }; + const expected = { + a: { b: { d: [3] } }, + e: [3], + }; + expect(deepMerge(source, target)).toStrictEqual(expected); + }); + + test("should union arrays using mergeArrays = 'union'", () => { + const source = { + a: { b: { d: [1, 2] } }, + e: [1, 2], + }; + const target = { + a: { b: { d: [2, 3] } }, + e: [1, 3], + }; + const expected = { + a: { b: { d: [1, 2, 3] } }, + e: [1, 2, 3], + }; + expect(deepMerge(source, target, 'union')).toStrictEqual(expected); + }); + + test("should intersect arrays using mergeArrays = 'intersection'", () => { + const source = { + a: { b: { d: [1, 2] } }, + e: [1, 2], + }; + const target = { + a: { b: { d: [2, 3] } }, + e: [3], + }; + const expected = { + a: { b: { d: [2] } }, + e: [], + }; + expect(deepMerge(source, target, 'intersection')).toStrictEqual(expected); + }); + + test("should concatenate arrays using mergeArrays = 'concat'", () => { + const source = { + a: { b: { d: [1, 2] } }, + e: [1, 2], + }; + const target = { + a: { b: { d: [2, 3] } }, + e: [3], + }; + const expected = { + a: { b: { d: [1, 2, 2, 3] } }, + e: [1, 2, 3], + }; + expect(deepMerge(source, target, 'concat')).toStrictEqual(expected); + }); +}); diff --git a/src/utils/auth/index.ts b/src/utils/auth/index.ts new file mode 100644 index 0000000..2ec0567 --- /dev/null +++ b/src/utils/auth/index.ts @@ -0,0 +1,25 @@ +import { Persistent, BasicKeys } from '@/utils/cache/persistent'; +import { CacheTypeEnum, TOKEN_KEY } from '@/enums/cacheEnum'; +import projectSetting from '@/settings/projectSetting'; + +const { permissionCacheType } = projectSetting; +const isLocal = permissionCacheType === CacheTypeEnum.LOCAL; + +export function getToken() { + return getAuthCache(TOKEN_KEY); +} + +export function getAuthCache(key: BasicKeys) { + const fn = isLocal ? Persistent.getLocal : Persistent.getSession; + return fn(key) as T; +} + +export function setAuthCache(key: BasicKeys, value) { + const fn = isLocal ? Persistent.setLocal : Persistent.setSession; + return fn(key, value, true); +} + +export function clearAuthCache(immediate = true) { + const fn = isLocal ? Persistent.clearLocal : Persistent.clearSession; + return fn(immediate); +} diff --git a/src/utils/base.ts b/src/utils/base.ts new file mode 100644 index 0000000..5d270de --- /dev/null +++ b/src/utils/base.ts @@ -0,0 +1,46 @@ +/** + * 日期格式化 + */ + export function formatDate(v, format) { + if (!v) return ""; + var d = v; + if (typeof v === 'string') { + if (v.indexOf("/Date(") > -1) + d = new Date(parseInt(v.replace("/Date(", "").replace(")/", ""), 10)); + else + d = new Date(Date.parse(v.replace(/-/g, "/").replace("T", " ").split(".")[0]));//.split(".")[0] 用来处理出现毫秒的情况,截取掉.xxx,否则会出错 + } + var o = { + "M+": d.getMonth() + 1, //month + "d+": d.getDate(), //day + "h+": d.getHours(), //hour + "H+": d.getHours(), //hour + "m+": d.getMinutes(), //minute + "s+": d.getSeconds(), //second + "q+": Math.floor((d.getMonth() + 3) / 3), //quarter + "S": d.getMilliseconds() //millisecond + }; + if (/(y+)/.test(format)) { + format = format.replace(RegExp.$1, (d.getFullYear() + "").substr(4 - RegExp.$1.length)); + } + for (var k in o) { + if (new RegExp("(" + k + ")").test(format)) { + format = format.replace(RegExp.$1, RegExp.$1.length == 1 ? o[k] : ("00" + o[k]).substr(("" + o[k]).length)); + } + } + return format; + +} + + +export function dateFormat(date,format = 'yyyy-MM-dd hh:mm:ss'){ + return formatDate(date,format); +} + // 数组去重 + export function unique(arr) { + let map = new Map(); + for (let item of arr) { + map.set(item.id, item); + } + return [...map.values()]; +} \ No newline at end of file diff --git a/src/utils/bem.ts b/src/utils/bem.ts new file mode 100644 index 0000000..cc172ac --- /dev/null +++ b/src/utils/bem.ts @@ -0,0 +1,53 @@ +import { prefixCls } from '@/settings/designSetting'; + +type Mod = string | { [key: string]: any }; +type Mods = Mod | Mod[]; + +export type BEM = ReturnType; + +function genBem(name: string, mods?: Mods): string { + if (!mods) { + return ''; + } + + if (typeof mods === 'string') { + return ` ${name}--${mods}`; + } + + // ArrayConstructor.isArray(arg: any): arg is any[] + if (Array.isArray(mods)) { + return (mods as Mod[]).reduce((ret, item) => ret + genBem(name, item), ''); + } + + return Object.keys(mods).reduce((ret, key) => ret + (mods[key] ? genBem(name, key) : ''), ''); +} + +/** + * bem helper + * b() // 'button' + * b('text') // 'button__text' + * b({ disabled }) // 'button button--disabled' + * b('text', { disabled }) // 'button__text button__text--disabled' + * b(['disabled', 'primary']) // 'button button--disabled button--primary' + */ +export function buildBEM(name: string) { + return (el?: Mods, mods?: Mods): Mods => { + if (el && typeof el !== 'string') { + mods = el; + el = ''; + } + + el = el ? `${name}__${el}` : name; + + return `${el}${genBem(el, mods)}`; + }; +} + +export function createBEM(name: string) { + return [buildBEM(`${prefixCls}-${name}`)]; +} + +export function createNamespace(name: string) { + const prefixedName = `${prefixCls}-${name}`; + return [prefixedName, buildBEM(prefixedName)] as const; +} diff --git a/src/utils/cache/index.ts b/src/utils/cache/index.ts new file mode 100644 index 0000000..62df442 --- /dev/null +++ b/src/utils/cache/index.ts @@ -0,0 +1,31 @@ +import { getStorageShortName } from '@/utils/env'; +import { createStorage as create, CreateStorageParams } from './storageCache'; +import { SHOULD_ENABLE_STORAGE_ENCRYPTION, DEFAULT_CACHE_TIME } from '@/settings/encryptionSetting'; + +export type Options = Partial; + +const createOptions = (storage: Storage, options: Options = {}): Options => { + return { + // No encryption in debug mode + hasEncrypt: SHOULD_ENABLE_STORAGE_ENCRYPTION, + storage, + prefixKey: getStorageShortName(), + ...options, + }; +}; + +export const WebStorage = create(createOptions(sessionStorage)); + +export const createStorage = (storage: Storage = sessionStorage, options: Options = {}) => { + return create(createOptions(storage, options)); +}; + +export const createSessionStorage = (options: Options = {}) => { + return createStorage(sessionStorage, { ...options, timeout: DEFAULT_CACHE_TIME }); +}; + +export const createLocalStorage = (options: Options = {}) => { + return createStorage(localStorage, { ...options, timeout: DEFAULT_CACHE_TIME }); +}; + +export default WebStorage; diff --git a/src/utils/cache/memory.ts b/src/utils/cache/memory.ts new file mode 100644 index 0000000..8d2cfd1 --- /dev/null +++ b/src/utils/cache/memory.ts @@ -0,0 +1,107 @@ +export interface Cache { + value?: V; + timeoutId?: ReturnType; + time?: number; + alive?: number; +} + +const NOT_ALIVE = 0; + +export class Memory { + private cache: { [key in keyof T]?: Cache } = {}; + private alive: number; + + constructor(alive = NOT_ALIVE) { + // Unit second + this.alive = alive * 1000; + } + + get getCache() { + return this.cache; + } + + setCache(cache) { + this.cache = cache; + } + + // get(key: K) { + // const item = this.getItem(key); + // const time = item?.time; + // if (!isNil(time) && time < new Date().getTime()) { + // this.remove(key); + // } + // return item?.value ?? undefined; + // } + + get(key: K) { + return this.cache[key]; + } + + set(key: K, value: V, expires?: number) { + let item = this.get(key); + + if (!expires || (expires as number) <= 0) { + expires = this.alive; + } + if (item) { + if (item.timeoutId) { + clearTimeout(item.timeoutId); + item.timeoutId = undefined; + } + item.value = value; + } else { + item = { value, alive: expires }; + this.cache[key] = item; + } + + if (!expires) { + return value; + } + const now = new Date().getTime(); + /** + * Prevent overflow of the setTimeout Maximum delay value + * Maximum delay value 2,147,483,647 ms + * https://developer.mozilla.org/en-US/docs/Web/API/setTimeout#maximum_delay_value + */ + item.time = expires > now ? expires : now + expires; + item.timeoutId = setTimeout( + () => { + this.remove(key); + }, + expires > now ? expires - now : expires, + ); + + return value; + } + + remove(key: K) { + const item = this.get(key); + Reflect.deleteProperty(this.cache, key); + if (item) { + clearTimeout(item.timeoutId!); + return item.value; + } + } + + resetCache(cache: { [K in keyof T]: Cache }) { + Object.keys(cache).forEach((key) => { + const k = key as any as keyof T; + const item = cache[k]; + if (item && item.time) { + const now = new Date().getTime(); + const expire = item.time; + if (expire > now) { + this.set(k, item.value, expire); + } + } + }); + } + + clear() { + Object.keys(this.cache).forEach((key) => { + const item = this.cache[key]; + item.timeoutId && clearTimeout(item.timeoutId); + }); + this.cache = {}; + } +} diff --git a/src/utils/cache/persistent.ts b/src/utils/cache/persistent.ts new file mode 100644 index 0000000..13a8bf2 --- /dev/null +++ b/src/utils/cache/persistent.ts @@ -0,0 +1,140 @@ +import type { LockInfo, UserInfo, TableSetting } from '#/store'; +import type { ProjectConfig } from '#/config'; +import type { RouteLocationNormalized } from 'vue-router'; + +import { createLocalStorage, createSessionStorage } from '@/utils/cache'; +import { Memory } from './memory'; +import { + SUBJECT_KEY, + SUBJECT_TITLE, + SUBJECT_LOGO_TITLE, + TOKEN_KEY, + USER_INFO_KEY, + ROLES_KEY, + LOCK_INFO_KEY, + PROJ_CFG_KEY, + APP_LOCAL_CACHE_KEY, + APP_SESSION_CACHE_KEY, + MULTIPLE_TABS_KEY, + TABLE_SETTING_KEY, +} from '@/enums/cacheEnum'; +import { DEFAULT_CACHE_TIME } from '@/settings/encryptionSetting'; +import { toRaw } from 'vue'; +import { pick, omit } from 'lodash-es'; + +interface BasicStore { + [SUBJECT_KEY]: string | number | null | undefined; + [SUBJECT_TITLE]: string | number | null | undefined; + [SUBJECT_LOGO_TITLE]: string | number | null | undefined; + [TOKEN_KEY]: string | number | null | undefined; + [USER_INFO_KEY]: UserInfo; + [ROLES_KEY]: string[]; + [LOCK_INFO_KEY]: LockInfo; + [PROJ_CFG_KEY]: ProjectConfig; + [MULTIPLE_TABS_KEY]: RouteLocationNormalized[]; + [TABLE_SETTING_KEY]: Partial; +} + +type LocalStore = BasicStore; + +type SessionStore = BasicStore; + +export type BasicKeys = keyof BasicStore; +type LocalKeys = keyof LocalStore; +type SessionKeys = keyof SessionStore; + +const ls = createLocalStorage(); +const ss = createSessionStorage(); + +const localMemory = new Memory(DEFAULT_CACHE_TIME); +const sessionMemory = new Memory(DEFAULT_CACHE_TIME); + +function initPersistentMemory() { + const localCache = ls.get(APP_LOCAL_CACHE_KEY); + const sessionCache = ss.get(APP_SESSION_CACHE_KEY); + localCache && localMemory.resetCache(localCache); + sessionCache && sessionMemory.resetCache(sessionCache); +} + +export class Persistent { + static getLocal(key: LocalKeys) { + return localMemory.get(key)?.value as Nullable; + } + + static setLocal(key: LocalKeys, value: LocalStore[LocalKeys], immediate = false): void { + localMemory.set(key, toRaw(value)); + immediate && ls.set(APP_LOCAL_CACHE_KEY, localMemory.getCache); + } + + static removeLocal(key: LocalKeys, immediate = false): void { + localMemory.remove(key); + immediate && ls.set(APP_LOCAL_CACHE_KEY, localMemory.getCache); + } + + static clearLocal(immediate = false): void { + localMemory.clear(); + immediate && ls.clear(); + } + + static getSession(key: SessionKeys) { + return sessionMemory.get(key)?.value as Nullable; + } + + static setSession(key: SessionKeys, value: SessionStore[SessionKeys], immediate = false): void { + sessionMemory.set(key, toRaw(value)); + immediate && ss.set(APP_SESSION_CACHE_KEY, sessionMemory.getCache); + } + + static removeSession(key: SessionKeys, immediate = false): void { + sessionMemory.remove(key); + immediate && ss.set(APP_SESSION_CACHE_KEY, sessionMemory.getCache); + } + static clearSession(immediate = false): void { + sessionMemory.clear(); + immediate && ss.clear(); + } + + static clearAll(immediate = false) { + sessionMemory.clear(); + localMemory.clear(); + if (immediate) { + ls.clear(); + ss.clear(); + } + } +} + +window.addEventListener('beforeunload', function () { + // TOKEN_KEY 在登录或注销时已经写入到storage了,此处为了解决同时打开多个窗口时token不同步的问题 + // LOCK_INFO_KEY 在锁屏和解锁时写入,此处也不应修改 + ls.set(APP_LOCAL_CACHE_KEY, { + ...omit(localMemory.getCache, LOCK_INFO_KEY), + ...pick(ls.get(APP_LOCAL_CACHE_KEY), [TOKEN_KEY, USER_INFO_KEY, LOCK_INFO_KEY]), + }); + ss.set(APP_SESSION_CACHE_KEY, { + ...omit(sessionMemory.getCache, LOCK_INFO_KEY), + ...pick(ss.get(APP_SESSION_CACHE_KEY), [TOKEN_KEY, USER_INFO_KEY, LOCK_INFO_KEY]), + }); +}); + +function storageChange(e: any) { + const { key, newValue, oldValue } = e; + + if (!key) { + Persistent.clearAll(); + return; + } + + if (!!newValue && !!oldValue) { + if (APP_LOCAL_CACHE_KEY === key) { + Persistent.clearLocal(); + } + if (APP_SESSION_CACHE_KEY === key) { + Persistent.clearSession(); + } + } +} + +window.addEventListener('storage', storageChange); + +initPersistentMemory(); diff --git a/src/utils/cache/storageCache.ts b/src/utils/cache/storageCache.ts new file mode 100644 index 0000000..3250408 --- /dev/null +++ b/src/utils/cache/storageCache.ts @@ -0,0 +1,111 @@ +import { cacheCipher } from '@/settings/encryptionSetting'; +import { isNil } from '@/utils/is'; +import { Encryption, EncryptionFactory, EncryptionParams } from '@/utils/cipher'; + +export interface CreateStorageParams extends EncryptionParams { + prefixKey: string; + storage: Storage; + hasEncrypt: boolean; + timeout?: Nullable; +} +// TODO 移除此文件夹下全部代码 +export const createStorage = ({ + prefixKey = '', + storage = sessionStorage, + key = cacheCipher.key, + iv = cacheCipher.iv, + timeout = null, + hasEncrypt = true, +}: Partial = {}) => { + if (hasEncrypt && [key.length, iv.length].some((item) => item !== 16)) { + throw new Error('When hasEncrypt is true, the key or iv must be 16 bits!'); + } + + const persistEncryption: Encryption = EncryptionFactory.createAesEncryption({ + key: cacheCipher.key, + iv: cacheCipher.iv, + }); + /** + * Cache class + * Construction parameters can be passed into sessionStorage, localStorage, + * @class Cache + * @example + */ + const WebStorage = class WebStorage { + private storage: Storage; + private prefixKey?: string; + private encryption: Encryption; + private hasEncrypt: boolean; + /** + * + * @param {*} storage + */ + constructor() { + this.storage = storage; + this.prefixKey = prefixKey; + this.encryption = persistEncryption; + this.hasEncrypt = hasEncrypt; + } + + private getKey(key: string) { + return `${this.prefixKey}${key}`.toUpperCase(); + } + + /** + * Set cache + * @param {string} key + * @param {*} value + * @param {*} expire Expiration time in seconds + * @memberof Cache + */ + set(key: string, value: any, expire: number | null = timeout) { + const stringData = JSON.stringify({ + value, + time: Date.now(), + expire: !isNil(expire) ? new Date().getTime() + expire * 1000 : null, + }); + const stringifyValue = this.hasEncrypt ? this.encryption.encrypt(stringData) : stringData; + this.storage.setItem(this.getKey(key), stringifyValue); + } + + /** + * Read cache + * @param {string} key + * @param {*} def + * @memberof Cache + */ + get(key: string, def: any = null): any { + const val = this.storage.getItem(this.getKey(key)); + if (!val) return def; + + try { + const decVal = this.hasEncrypt ? this.encryption.decrypt(val) : val; + const data = JSON.parse(decVal); + const { value, expire } = data; + if (isNil(expire) || expire >= new Date().getTime()) { + return value; + } + this.remove(key); + } catch (e) { + return def; + } + } + + /** + * Delete cache based on key + * @param {string} key + * @memberof Cache + */ + remove(key: string) { + this.storage.removeItem(this.getKey(key)); + } + + /** + * Delete all caches of this instance + */ + clear(): void { + this.storage.clear(); + } + }; + return new WebStorage(); +}; diff --git a/src/utils/cipher.ts b/src/utils/cipher.ts new file mode 100644 index 0000000..cbc2242 --- /dev/null +++ b/src/utils/cipher.ts @@ -0,0 +1,159 @@ +import { decrypt as aesDecrypt, encrypt as aesEncrypt } from 'crypto-js/aes'; +import UTF8, { parse } from 'crypto-js/enc-utf8'; +import pkcs7 from 'crypto-js/pad-pkcs7'; +import CTR from 'crypto-js/mode-ctr'; +import Base64 from 'crypto-js/enc-base64'; +import MD5 from 'crypto-js/md5'; +import SHA256 from 'crypto-js/sha256'; +import SHA512 from 'crypto-js/sha512'; + +// Define an interface for encryption +// 定义一个加密器的接口 +export interface Encryption { + encrypt(plainText: string): string; + decrypt(cipherText: string): string; +} +// Define an interface for Hashing +// 定义一个哈希算法的接口 +export interface Hashing { + hash(data: string): string; +} + +export interface EncryptionParams { + key: string; + iv: string; +} + +class AesEncryption implements Encryption { + private readonly key; + private readonly iv; + + constructor({ key, iv }: EncryptionParams) { + this.key = parse(key); + this.iv = parse(iv); + } + + get getOptions() { + return { + mode: CTR, + padding: pkcs7, + iv: this.iv, + }; + } + + encrypt(plainText: string) { + return aesEncrypt(plainText, this.key, this.getOptions).toString(); + } + + decrypt(cipherText: string) { + return aesDecrypt(cipherText, this.key, this.getOptions).toString(UTF8); + } +} + +// Define a singleton class for Base64 encryption +class Base64Encryption implements Encryption { + private static instance: Base64Encryption; + + private constructor() {} + + // Get the singleton instance + // 获取单例实例 + public static getInstance(): Base64Encryption { + if (!Base64Encryption.instance) { + Base64Encryption.instance = new Base64Encryption(); + } + return Base64Encryption.instance; + } + + encrypt(plainText: string) { + return UTF8.parse(plainText).toString(Base64); + } + + decrypt(cipherText: string) { + return Base64.parse(cipherText).toString(UTF8); + } +} + +// Define a singleton class for MD5 Hashing +class MD5Hashing implements Hashing { + private static instance: MD5Hashing; + + private constructor() {} + + // Get the singleton instance + // 获取单例实例 + public static getInstance(): MD5Hashing { + if (!MD5Hashing.instance) { + MD5Hashing.instance = new MD5Hashing(); + } + return MD5Hashing.instance; + } + + hash(plainText: string) { + return MD5(plainText).toString(); + } +} + +// Define a singleton class for SHA256 Hashing +class SHA256Hashing implements Hashing { + private static instance: SHA256Hashing; + + private constructor() {} + + // Get the singleton instance + // 获取单例实例 + public static getInstance(): SHA256Hashing { + if (!SHA256Hashing.instance) { + SHA256Hashing.instance = new SHA256Hashing(); + } + return SHA256Hashing.instance; + } + + hash(plainText: string) { + return SHA256(plainText).toString(); + } +} + +// Define a singleton class for SHA512 Hashing +class SHA512Hashing implements Hashing { + private static instance: SHA512Hashing; + + private constructor() {} + + // Get the singleton instance + // 获取单例实例 + public static getInstance(): SHA256Hashing { + if (!SHA512Hashing.instance) { + SHA512Hashing.instance = new SHA512Hashing(); + } + return SHA512Hashing.instance; + } + + hash(plainText: string) { + return SHA512(plainText).toString(); + } +} + +export class EncryptionFactory { + public static createAesEncryption(params: EncryptionParams): Encryption { + return new AesEncryption(params); + } + + public static createBase64Encryption(): Encryption { + return Base64Encryption.getInstance(); + } +} + +export class HashingFactory { + public static createMD5Hashing(): Hashing { + return MD5Hashing.getInstance(); + } + + public static createSHA256Hashing(): Hashing { + return SHA256Hashing.getInstance(); + } + + public static createSHA512Hashing(): Hashing { + return SHA512Hashing.getInstance(); + } +} diff --git a/src/utils/color.ts b/src/utils/color.ts new file mode 100644 index 0000000..3c0ca5e --- /dev/null +++ b/src/utils/color.ts @@ -0,0 +1,151 @@ +/** + * 判断是否 十六进制颜色值. + * 输入形式可为 #fff000 #f00 + * + * @param String color 十六进制颜色值 + * @return Boolean + */ +export function 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 function 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 function hexToRGB(hex: string) { + 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 'RGB(' + sColorChange.join(',') + ')'; + } + return sHex; +} + +export function 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 function 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 function 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 + */ +function 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 + */ +function 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 + */ +function 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 function 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 + */ +function 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)}`; +} diff --git a/src/utils/copyTextToClipboard.ts b/src/utils/copyTextToClipboard.ts new file mode 100644 index 0000000..236e914 --- /dev/null +++ b/src/utils/copyTextToClipboard.ts @@ -0,0 +1,41 @@ +import { message } from 'ant-design-vue'; + +// `navigator.clipboard` 可能因浏览器设置或浏览器兼容而造成兼容问题 +export function copyText(text: string, prompt: string | null = '已成功复制到剪切板!') { + if (navigator.clipboard) { + return navigator.clipboard + .writeText(text) + .then(() => { + prompt && message.success(prompt); + }) + .catch((error) => { + message.error('复制失败!' + error.message); + return error; + }); + } + if (Reflect.has(document, 'execCommand')) { + return new Promise((resolve, reject) => { + try { + const textArea = document.createElement('textarea'); + textArea.value = text; + // 在手机 Safari 浏览器中,点击复制按钮,整个页面会跳动一下 + textArea.style.width = '0'; + textArea.style.position = 'fixed'; + textArea.style.left = '-999px'; + textArea.style.top = '10px'; + textArea.setAttribute('readonly', 'readonly'); + document.body.appendChild(textArea); + textArea.select(); + document.execCommand('copy'); + document.body.removeChild(textArea); + + prompt && message.success(prompt); + resolve(); + } catch (error) { + message.error('复制失败!' + error.message); + reject(error); + } + }); + } + return Promise.reject(`"navigator.clipboard" 或 "document.execCommand" 中存在API错误, 拷贝失败!`); +} diff --git a/src/utils/dateUtil.ts b/src/utils/dateUtil.ts new file mode 100644 index 0000000..e18387d --- /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 0000000..bc80613 --- /dev/null +++ b/src/utils/domUtils.ts @@ -0,0 +1,180 @@ +import type { FunctionArgs } from '@vueuse/core'; +import { upperFirst } from 'lodash-es'; + +export interface ViewportOffsetResult { + left: number; + top: number; + right: number; + bottom: number; + rightIncludeBody: number; + bottomIncludeBody: number; +} + +export function getBoundingClientRect(element: Element): DOMRect | number { + if (!element || !element.getBoundingClientRect) { + return 0; + } + return element.getBoundingClientRect(); +} + +function trim(string: string) { + return (string || '').replace(/^[\s\uFEFF]+|[\s\uFEFF]+$/g, ''); +} + +/* 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); + } +} +/** + * Get the left and top offset of the current element + * left: the distance between the leftmost element and the left side of the document + * top: the distance from the top of the element to the top of the document + * right: the distance from the far right of the element to the right of the document + * bottom: the distance from the bottom of the element to the bottom of the document + * rightIncludeBody: the distance between the leftmost element and the right side of the document + * bottomIncludeBody: the distance from the bottom of the element to the bottom of the document + * + * @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, + }; +} + +export function hackCss(attr: string, value: string) { + const prefix: string[] = ['webkit', 'Moz', 'ms', 'OT']; + + const styleObj: any = {}; + prefix.forEach((item) => { + styleObj[`${item}${upperFirst(attr)}`] = value; + }); + return { + ...styleObj, + [attr]: value, + }; +} + +/* istanbul ignore next */ +export function on( + element: Element | HTMLElement | Document | Window, + event: string, + handler: EventListenerOrEventListenerObject, +): void { + if (element && event && handler) { + element.addEventListener(event, handler, false); + } +} + +/* istanbul ignore next */ +export function off( + element: Element | HTMLElement | Document | Window, + event: string, + handler: Fn, +): void { + if (element && event && handler) { + element.removeEventListener(event, handler, false); + } +} + +/* istanbul ignore next */ +export function once(el: HTMLElement, event: string, fn: EventListener): void { + const listener = function (this: any, ...args: unknown[]) { + if (fn) { + fn.apply(this, args as [evt: Event]); + } + off(el, event, listener); + }; + on(el, event, listener); +} + +export function useRafThrottle(fn: T): T { + let locked = false; + // @ts-ignore + return function (...args: any[]) { + if (locked) return; + locked = true; + window.requestAnimationFrame(() => { + // @ts-ignore + fn.apply(this, args); + locked = false; + }); + }; +} diff --git a/src/utils/env.ts b/src/utils/env.ts new file mode 100644 index 0000000..356fb02 --- /dev/null +++ b/src/utils/env.ts @@ -0,0 +1,102 @@ +import type { GlobEnvConfig } from '#/config'; +import pkg from '../../package.json'; +import { API_ADDRESS } from '@/enums/cacheEnum'; + +export function getCommonStoragePrefix() { + const { VITE_GLOB_APP_TITLE } = getAppEnvConfig(); + return `${VITE_GLOB_APP_TITLE.replace(/\s/g, '_')}__${getEnv()}`.toUpperCase(); +} + +// Generate cache key according to version +export function getStorageShortName() { + return `${getCommonStoragePrefix()}${`__${pkg.version}`}__`.toUpperCase(); +} + +const getVariableName = (title: string) => { + function strToHex(str: string) { + const result: string[] = []; + for (let i = 0; i < str.length; ++i) { + const hex = str.charCodeAt(i).toString(16); + result.push(('000' + hex).slice(-4)); + } + return result.join('').toUpperCase(); + } + return `__PRODUCTION__${strToHex(title) || '__APP'}__CONF__`.toUpperCase().replace(/\s/g, ''); +}; + +export function getAppEnvConfig() { + const ENV_NAME = getVariableName(import.meta.env.VITE_GLOB_APP_TITLE); + const ENV = import.meta.env.DEV + ? // Get the global configuration (the configuration will be extracted independently when packaging) + (import.meta.env as unknown as GlobEnvConfig) + : (window[ENV_NAME] as unknown as GlobEnvConfig); + const { + VITE_GLOB_APP_TITLE, + VITE_GLOB_APP_EN_TITLE, + VITE_GLOB_API_URL_PREFIX, + VITE_GLOB_UPLOAD_URL, + VITE_GLOB_APP_LOGO, + VITE_GLOB_INFO_IMAGE_URL, + VITE_GLOB_APP_MANAGEMENT_UNIT, + VITE_GLOB_APP_TECHINICAL_SUPPORT, + VITE_GLOB_APP_VERSIONS, + VITE_GLOB_YINGXIANG_SERVER, + VITE_GLOB_FILE_PREVIEW + } = ENV; + let { VITE_GLOB_API_URL } = ENV; + if (localStorage.getItem(API_ADDRESS)) { + const address = JSON.parse(localStorage.getItem(API_ADDRESS) || '{}'); + if (address?.key) VITE_GLOB_API_URL = address?.val; + } + return { + VITE_GLOB_APP_TITLE, + VITE_GLOB_APP_EN_TITLE, + VITE_GLOB_API_URL, + VITE_GLOB_API_URL_PREFIX, + VITE_GLOB_UPLOAD_URL, + VITE_GLOB_APP_LOGO, + VITE_GLOB_INFO_IMAGE_URL, + VITE_GLOB_APP_MANAGEMENT_UNIT, + VITE_GLOB_APP_TECHINICAL_SUPPORT, + VITE_GLOB_APP_VERSIONS, + VITE_GLOB_YINGXIANG_SERVER, + VITE_GLOB_FILE_PREVIEW + }; +} + +/** + * @description: Development mode + */ +export const devMode = 'development'; + +/** + * @description: Production mode + */ +export const prodMode = 'production'; + +/** + * @description: Get environment variables + * @returns: + * @example: + */ +export function getEnv(): string { + return import.meta.env.MODE; +} + +/** + * @description: Is it a development mode + * @returns: + * @example: + */ +export function isDevMode(): boolean { + return import.meta.env.DEV; +} + +/** + * @description: Is it a production mode + * @returns: + * @example: + */ +export function isProdMode(): boolean { + return import.meta.env.PROD; +} diff --git a/src/utils/event/index.ts b/src/utils/event/index.ts new file mode 100644 index 0000000..3a60d7c --- /dev/null +++ b/src/utils/event/index.ts @@ -0,0 +1,42 @@ +import ResizeObserver from 'resize-observer-polyfill'; + +const isServer = typeof window === 'undefined'; + +/* istanbul ignore next */ +function resizeHandler(entries: any[]) { + for (const entry of entries) { + const listeners = entry.target.__resizeListeners__ || []; + if (listeners.length) { + listeners.forEach((fn: () => any) => { + fn(); + }); + } + } +} + +/* istanbul ignore next */ +export function addResizeListener(element: any, fn: () => any) { + if (isServer) return; + if (!element.__resizeListeners__) { + element.__resizeListeners__ = []; + element.__ro__ = new ResizeObserver(resizeHandler); + element.__ro__.observe(element); + } + element.__resizeListeners__.push(fn); +} + +/* istanbul ignore next */ +export function removeResizeListener(element: any, fn: () => any) { + if (!element || !element.__resizeListeners__) return; + element.__resizeListeners__.splice(element.__resizeListeners__.indexOf(fn), 1); + if (!element.__resizeListeners__.length) { + element.__ro__.disconnect(); + } +} + +export function triggerWindowResize() { + const event = document.createEvent('HTMLEvents'); + event.initEvent('resize', true, true); + (event as any).eventType = 'message'; + window.dispatchEvent(event); +} diff --git a/src/utils/factory/createAsyncComponent.tsx b/src/utils/factory/createAsyncComponent.tsx new file mode 100644 index 0000000..78d5c61 --- /dev/null +++ b/src/utils/factory/createAsyncComponent.tsx @@ -0,0 +1,70 @@ +import { + AsyncComponentLoader, + Component, + ComponentPublicInstance, + defineAsyncComponent, + // FunctionalComponent, CSSProperties +} from 'vue'; +import { Spin } from 'ant-design-vue'; +import { noop } from '@/utils'; + +// const Loading: FunctionalComponent<{ size: 'small' | 'default' | 'large' }> = (props) => { +// const style: CSSProperties = { +// position: 'absolute', +// display: 'flex', +// justifyContent: 'center', +// alignItems: 'center', +// }; +// return ( +//
+// +//
+// ); +// }; + +interface Options { + size?: 'default' | 'small' | 'large'; + delay?: number; + timeout?: number; + loading?: boolean; + retry?: boolean; +} + +export function createAsyncComponent< + T extends Component = { + new (): ComponentPublicInstance; + }, +>(loader: AsyncComponentLoader, options: Options = {}) { + const { size = 'small', delay = 100, timeout = 30000, loading = false, retry = true } = options; + return defineAsyncComponent({ + loader, + loadingComponent: loading ? : undefined, + // The error component will be displayed if a timeout is + // provided and exceeded. Default: Infinity. + // TODO + timeout, + // errorComponent + // Defining if component is suspensible. Default: true. + // suspensible: false, + delay, + /** + * + * @param {*} error Error message object + * @param {*} retry A function that indicating whether the async component should retry when the loader promise rejects + * @param {*} fail End of failure + * @param {*} attempts Maximum allowed retries number + */ + onError: !retry + ? noop + : (error, retry, fail, attempts) => { + if (error.message.match(/fetch/) && attempts <= 3) { + // retry on fetch errors, 3 max attempts + retry(); + } else { + // Note that retry/fail are like resolve/reject of a promise: + // one of them must be called for the error handling to continue. + fail(); + } + }, + }); +} diff --git a/src/utils/file/base64Conver.ts b/src/utils/file/base64Conver.ts new file mode 100644 index 0000000..6751d97 --- /dev/null +++ b/src/utils/file/base64Conver.ts @@ -0,0 +1,41 @@ +/** + * @description: base64 to blob + */ +export function dataURLtoBlob(base64Buf: string): Blob { + const arr = base64Buf.split(','); + const typeItem = arr[0]; + const mime = typeItem.match(/:(.*?);/)![1]; + const bstr = window.atob(arr[1]); + let n = bstr.length; + const u8arr = new Uint8Array(n); + while (n--) { + u8arr[n] = bstr.charCodeAt(n); + } + return new Blob([u8arr], { type: mime }); +} + +/** + * img url to base64 + * @param url + */ +export function urlToBase64(url: string, mineType?: string): Promise { + return new Promise((resolve, reject) => { + let canvas = document.createElement('CANVAS') as Nullable; + const ctx = canvas!.getContext('2d'); + + const img = new Image(); + img.crossOrigin = ''; + img.onload = function () { + if (!canvas || !ctx) { + return reject(); + } + canvas.height = img.height; + canvas.width = img.width; + ctx.drawImage(img, 0, 0); + const dataURL = canvas.toDataURL(mineType || 'image/png'); + canvas = null; + resolve(dataURL); + }; + img.src = url; + }); +} diff --git a/src/utils/file/download.ts b/src/utils/file/download.ts new file mode 100644 index 0000000..6af9ab4 --- /dev/null +++ b/src/utils/file/download.ts @@ -0,0 +1,96 @@ +import { openWindow } from '..'; +import { dataURLtoBlob, urlToBase64 } from './base64Conver'; + +/** + * Download online pictures + * @param url + * @param filename + * @param mime + * @param bom + */ +export function downloadByOnlineUrl(url: string, filename: string, mime?: string, bom?: BlobPart) { + urlToBase64(url).then((base64) => { + downloadByBase64(base64, filename, mime, bom); + }); +} + +/** + * Download pictures based on base64 + * @param buf + * @param filename + * @param mime + * @param bom + */ +export function downloadByBase64(buf: string, filename: string, mime?: string, bom?: BlobPart) { + const base64Buf = dataURLtoBlob(buf); + downloadByData(base64Buf, filename, mime, bom); +} + +/** + * Download according to the background interface file stream + * @param {*} data + * @param {*} filename + * @param {*} mime + * @param {*} bom + */ +export function downloadByData(data: BlobPart, filename: string, mime?: string, bom?: BlobPart) { + const blobData = typeof bom !== 'undefined' ? [bom, data] : [data]; + const blob = new Blob(blobData, { type: mime || 'application/octet-stream' }); + + const blobURL = window.URL.createObjectURL(blob); + const tempLink = document.createElement('a'); + tempLink.style.display = 'none'; + tempLink.href = blobURL; + tempLink.setAttribute('download', filename); + if (typeof tempLink.download === 'undefined') { + tempLink.setAttribute('target', '_blank'); + } + document.body.appendChild(tempLink); + tempLink.click(); + document.body.removeChild(tempLink); + window.URL.revokeObjectURL(blobURL); +} + +/** + * Download file according to file address + * @param {*} sUrl + */ +export function downloadByUrl({ + url, + target = '_blank', + fileName, +}: { + url: string; + target?: TargetContext; + fileName?: string; +}): boolean { + const isChrome = window.navigator.userAgent.toLowerCase().indexOf('chrome') > -1; + const isSafari = window.navigator.userAgent.toLowerCase().indexOf('safari') > -1; + + if (/(iP)/g.test(window.navigator.userAgent)) { + console.error('Your browser does not support download!'); + return false; + } + if (isChrome || isSafari) { + const link = document.createElement('a'); + link.href = url; + link.target = target; + + if (link.download !== undefined) { + link.download = fileName || url.substring(url.lastIndexOf('/') + 1, url.length); + } + + if (document.createEvent) { + const e = document.createEvent('MouseEvents'); + e.initEvent('click', true, true); + link.dispatchEvent(e); + return true; + } + } + if (url.indexOf('?') === -1) { + url += '?download'; + } + + openWindow(url, { target }); + return true; +} diff --git a/src/utils/global.ts b/src/utils/global.ts new file mode 100644 index 0000000..a4b0c58 --- /dev/null +++ b/src/utils/global.ts @@ -0,0 +1,256 @@ +// @/utils/global +import { getLoad } from '@/api/sys/sysDataItemDetail'; + +// 全局变量配置 +export const getYearList = () => { + const num = 4; + const currentYear = new Date().getFullYear(); + // 存储年份数据的数组 + const list: any = []; + // 获取当前年份 + // year.value = Number(`${currentYear}`); + list.push({ + value: Number(`${currentYear}`), + label: Number(`${currentYear}`), + }); + // 获取后面几年的数据 + for (let i = 1; i <= num; i++) { + list.push({ + value: Number(`${currentYear - i}`), + label: Number(`${currentYear - i}`), + }); + } + return list; +}; +// 批次 +export const batchOptions = []; +// 年份 +export const yearOptions = getYearList(); + +// 判定结果 +export const mapTypeOptions = [ + { label: '合法', value: 0 }, + { label: '违法', value: 1 }, + { label: '其他', value: 2 }, +]; +export const keyIssuesIIMapTypeOptions = [ + { label: '合法', value: 0 }, + { label: '违法', value: 1 }, + { label: '其他', value: 2 }, + { label: '自建自用', value: 3 }, +]; +export const illegalTypeOptions = [ + { label: '非农化', value: 0 }, + { label: '非粮化', value: 1 }, +]; +export const measureOptions = [ + { label: '拆除复耕', value: 0 }, + { label: '补办手续', value: 1 }, +]; +export const keyIssuesIMeasureOptions = [ + { label: '拆除', value: 1 }, + { label: '拆除复耕', value: 2 }, +]; +export const redLineMeasureOptions = [ + { label: '恢复原地类', value: '0' }, + { label: '补办手续', value: '1' }, +]; +export const keyIssuesIIMeasureOptions = [ + { label: '拆除', value: 1 }, + { label: '没收', value: 2 }, +]; +export const mapStatusOptions = [ + { label: '待接收', value: '待接收' }, + { label: '待填报', value: '待填报' }, + { label: '待整改', value: '待整改' }, + { label: '市级驳回', value: '市级驳回' }, + { label: '县级驳回', value: '县级驳回' }, +]; +export const keyProblemSearchMapStatusOptions = [ + { label: '待接收', value: '待接收' }, + { label: '待填报', value: '待填报' }, + { label: '市级驳回', value: '市级驳回' }, + { label: '县级驳回', value: '县级驳回' }, +]; +export const keyProblemMapStatusOptions = [ + { label: '待接收', value: '待接收' }, + { label: '待填报', value: '待填报' }, + { label: '市级审核', value: '市级审核' }, + { label: '县级审核', value: '县级审核' }, + { label: '已归档', value: '已归档' }, +]; +export const auditMapStatusOptions = [ + { label: '市级驳回', value: '市级驳回' }, + { label: '县级驳回', value: '县级驳回' }, +]; +// 标注类型 +export const markTypeOptions = [ + { label: '在建', value: '在建' }, + { label: '已建成', value: '已建成' }, + { label: '持续变化', value: '持续变化' }, +]; +// 图斑来源 +export const patchSourceOptions = [ + { + label: '全域巡查', + value: '全域巡查', + }, + { + label: '卫片下发', + value: '卫片下发', + }, + // { + // label: '部级矿产卫片图斑', + // value: '部级矿产卫片图斑', + // }, + // { + // label: '省级矿产卫片图斑', + // value: '省级矿产卫片图斑', + // }, + { + label: '省级月度图斑', + value: '省级月度图斑', + }, +]; +export const isOverdueOptions = [ + { + label: '未超期', + value: 0, + }, + { + label: '已超期', + value: 1, + }, +]; +export const illegalTypeList = [ + { label: '非农化违法用地', value: 0 }, + { label: '非粮化违法用地', value: 1 }, +]; +export const resultOptions = [ + { label: '立案', value: 0 }, + { label: '非立案', value: 1 }, + { label: '移交其他部门处理', value: 2 }, + { label: '未处理', value: 3 }, +]; +export const resultNameOptions = [ + { + label: '立案', + value: '立案', + }, + { + label: '非立案', + value: '非立案', + }, + { + label: '移交其他部门处理', + value: '移交其他部门处理', + }, + { + label: '未处理', + value: '未处理', + }, +]; +export const qitaUseTOOptions = [ + { + label: '不改变原用地性质的光伏用地', + value: '1', + }, + { + label: '设施农业用地', + value: '2', + }, + { + label: '农村道路', + value: '3', + }, + { + label: '实地未变化', + value: '4', + }, + { + label: '临时用地', + value: '5', + }, +]; +export const nowStatusOptions = [ + { label: '待接收', value: '待接收' }, + { label: '待填报', value: '待填报' }, + { label: '待整改', value: '待整改' }, + { label: '市级审核', value: '市级审核' }, + { label: '县级审核', value: '县级审核' }, + { label: '已归档', value: '已归档' }, +]; +//获取近7个月的时间 +export const getMonth = () => { + //创建现在的时间 + const data = new Date(); + //获取年 + let year = data.getFullYear(); + //获取月 + let mon = data.getMonth() + 1; + let arry: any = []; + for (let i = 0; i < 6; i++) { + if (mon <= 0) { + year = year - 1; + mon = mon + 12; + } + arry.push({ + label: `${mon}月`, + value: mon, + }); + mon = mon - 1; + } + return arry.reverse(); +}; +export const monthOptions = getMonth(); +export const monthAllOptions = () => { + let arr: any = getMonth(); + arr.reverse().unshift({ label: '全部', value: 0 }); + return arr; +}; +// 根据字典async获取对应的筛选数据 +export const asyncGetOptions = async (code: string) => { + let arry: any = []; + await getLoad({ code: code }).then((res) => { + res.forEach((item: any) => { + arry.push({ + label: item.itemName, + value: item.itemValue, + }); + }); + }); + return arry; +}; +export const isChuliOptions = [ + { label: '是', value: '1' }, + { label: '否', value: '2' }, +]; +// export const keyIssusesIPatchSourceOptions = await asyncGetOptions('zd1tbly'); +// export const keyIssusesIIPatchSourceOptions = await asyncGetOptions('zd2tbly'); +// export const inspectionAuditPatchSourceOptions = await asyncGetOptions('xcsjtbly'); +// export const degrainingPatchSourceOptions = await asyncGetOptions('gdflhbly'); +// export const redLinePatchSourceOptions = await asyncGetOptions('redlinetbly'); + +export const getZhuantiName = () => { + let code = sessionStorage.getItem('SelectOtherZhuantiCode') + switch(code){ + case "0000001": + return '违法用地' + case "0000002": + return '巡察审计' + case "0000003": + return '非法采矿卫片下发' + case "0000004": + return '耕地非粮化' + case "0000005": + return '重点问题Ⅰ类' + case "0000006": + return '重点问题Ⅱ类' + case "0000007": + return '生态保护红线监管' + case "0000008": + return '生态修复' + case "100001": + return '非法采矿' + } +} \ No newline at end of file diff --git a/src/utils/helper/treeHelper.ts b/src/utils/helper/treeHelper.ts new file mode 100644 index 0000000..922a473 --- /dev/null +++ b/src/utils/helper/treeHelper.ts @@ -0,0 +1,216 @@ +interface TreeHelperConfig { + id: string; + children: string; + pid: string; +} + +// 默认配置 +const DEFAULT_CONFIG: TreeHelperConfig = { + id: 'id', + children: 'children', + pid: 'pid', +}; + +// 获取配置。 Object.assign 从一个或多个源对象复制到目标对象 +const getConfig = (config: Partial) => Object.assign({}, DEFAULT_CONFIG, config); + +// tree from list +// 列表中的树 +export function 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 function 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 function 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 function 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 function 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 function 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 function filter( + tree: T[], + func: (n: T) => boolean, + // Partial 将 T 中的所有属性设为可选 + config: Partial = {}, +): T[] { + // 获取配置 + config = getConfig(config); + const children = config.children as string; + + function listFilter(list: T[]) { + return list + .map((node: any) => ({ ...node })) + .filter((node) => { + // 递归调用 对含有children项 进行再次调用自身函数 listFilter + node[children] = node[children] && listFilter(node[children]); + // 执行传入的回调 func 进行过滤 + return func(node) || (node[children] && node[children].length); + }); + } + + return listFilter(tree); +} + +export function 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 + * @description: 提取树指定结构 + */ +export function treeMap(treeData: T[], opt: { children?: string; conversion: Fn }): T[] { + return treeData.map((item) => treeMapEach(item, opt)); +} + +/** + * @description: Extract tree specified structure + * @description: 提取树指定结构 + */ +export function 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 function 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/helper/tsxHelper.tsx b/src/utils/helper/tsxHelper.tsx new file mode 100644 index 0000000..920a274 --- /dev/null +++ b/src/utils/helper/tsxHelper.tsx @@ -0,0 +1,37 @@ +import { Slots } from 'vue'; +import { isFunction } from '@/utils/is'; +import { RenderOpts } from '@/components/Form'; + +/** + * @description: Get slot to prevent empty error + */ +export function getSlot(slots: Slots, slot = 'default', data?: any, opts?: RenderOpts) { + 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; + const params = { ...data, ...opts }; + return slotFn(params); +} + +/** + * extends slots + * @param slots + * @param excludeKeys + */ +export function extendSlots(slots: Slots, excludeKeys: string[] = []) { + const slotKeys = Object.keys(slots); + const ret: any = {}; + slotKeys.map((key) => { + if (excludeKeys.includes(key)) { + return null; + } + ret[key] = (data?: any) => getSlot(slots, key, data); + }); + return ret; +} diff --git a/src/utils/http/axios/Axios.ts b/src/utils/http/axios/Axios.ts new file mode 100644 index 0000000..6ae67f7 --- /dev/null +++ b/src/utils/http/axios/Axios.ts @@ -0,0 +1,250 @@ +import type { + AxiosRequestConfig, + AxiosInstance, + AxiosResponse, + AxiosError, + InternalAxiosRequestConfig, +} from 'axios'; +import type { RequestOptions, Result, UploadFileParams } from '#/axios'; +import type { CreateAxiosOptions } from './axiosTransform'; +import axios from 'axios'; +import qs from 'qs'; +import { AxiosCanceler } from './axiosCancel'; +import { isFunction } from '@/utils/is'; +import { cloneDeep } from 'lodash-es'; +import { ContentTypeEnum, RequestEnum } from '@/enums/httpEnum'; + +export * from './axiosTransform'; + +/** + * @description: axios module + */ +export class VAxios { + private axiosInstance: AxiosInstance; + private readonly options: CreateAxiosOptions; + + constructor(options: CreateAxiosOptions) { + this.options = options; + this.axiosInstance = axios.create(options); + this.setupInterceptors(); + } + + /** + * @description: Create axios instance + */ + private createAxios(config: CreateAxiosOptions): void { + this.axiosInstance = axios.create(config); + } + + private getTransform() { + const { transform } = this.options; + return transform; + } + + getAxios(): AxiosInstance { + return this.axiosInstance; + } + + /** + * @description: Reconfigure axios + */ + configAxios(config: CreateAxiosOptions) { + if (!this.axiosInstance) { + return; + } + this.createAxios(config); + } + + /** + * @description: Set general header + */ + setHeader(headers: any): void { + if (!this.axiosInstance) { + return; + } + Object.assign(this.axiosInstance.defaults.headers, headers); + } + + /** + * @description: Interceptor configuration 拦截器配置 + */ + private setupInterceptors() { + // const transform = this.getTransform(); + const { + axiosInstance, + options: { transform }, + } = this; + if (!transform) { + return; + } + const { + requestInterceptors, + requestInterceptorsCatch, + responseInterceptors, + responseInterceptorsCatch, + } = transform; + + const axiosCanceler = new AxiosCanceler(); + + // Request interceptor configuration processing + this.axiosInstance.interceptors.request.use((config: InternalAxiosRequestConfig) => { + // If cancel repeat request is turned on, then cancel repeat request is prohibited + const requestOptions = + (config as unknown as any).requestOptions ?? this.options.requestOptions; + const ignoreCancelToken = requestOptions?.ignoreCancelToken ?? true; + + !ignoreCancelToken && axiosCanceler.addPending(config); + + if (requestInterceptors && isFunction(requestInterceptors)) { + config = requestInterceptors(config, this.options); + } + return config; + }, undefined); + + // Request interceptor error capture + requestInterceptorsCatch && + isFunction(requestInterceptorsCatch) && + this.axiosInstance.interceptors.request.use(undefined, requestInterceptorsCatch); + + // Response result interceptor processing + this.axiosInstance.interceptors.response.use((res: AxiosResponse) => { + res && axiosCanceler.removePending(res.config); + if (responseInterceptors && isFunction(responseInterceptors)) { + res = responseInterceptors(res); + } + return res; + }, undefined); + + // Response result interceptor error capture + responseInterceptorsCatch && + isFunction(responseInterceptorsCatch) && + this.axiosInstance.interceptors.response.use(undefined, (error) => { + return responseInterceptorsCatch(axiosInstance, error); + }); + } + + /** + * @description: File Upload + */ + uploadFile(config: AxiosRequestConfig, params: UploadFileParams) { + const formData = new window.FormData(); + const customFilename = 'files'; + if (params.filename) { + formData.append(customFilename, params.file, params.filename); + } else { + formData.append(customFilename, params.file); + } + + if (params.data) { + Object.keys(params.data).forEach((key) => { + const value = params.data![key]; + if (Array.isArray(value)) { + value.forEach((item) => { + formData.append(`${key}[]`, item); + }); + return; + } + + formData.append(key, params.data![key]); + }); + } + return this.axiosInstance.request({ + ...config, + method: 'POST', + data: formData, + headers: { + 'Content-type': ContentTypeEnum.FORM_DATA, + // @ts-ignore + ignoreCancelToken: true, + }, + }); + } + + // support form-data + supportFormData(config: AxiosRequestConfig) { + const headers = config.headers || this.options.headers; + const contentType = headers?.['Content-Type'] || headers?.['content-type']; + + if ( + contentType !== ContentTypeEnum.FORM_URLENCODED || + !Reflect.has(config, 'data') || + config.method?.toUpperCase() === RequestEnum.GET + ) { + return config; + } + + return { + ...config, + data: qs.stringify(config.data, { arrayFormat: 'brackets' }), + }; + } + + get(config: AxiosRequestConfig, options?: RequestOptions): Promise { + return this.request({ ...config, method: 'GET' }, options); + } + + post(config: AxiosRequestConfig, options?: RequestOptions): Promise { + return this.request({ ...config, method: 'POST' }, options); + } + + put(config: AxiosRequestConfig, options?: RequestOptions): Promise { + return this.request({ ...config, method: 'PUT' }, options); + } + + delete(config: AxiosRequestConfig, options?: RequestOptions): Promise { + return this.request({ ...config, method: 'DELETE' }, options); + } + + request(config: AxiosRequestConfig, options?: RequestOptions): Promise { + let conf: CreateAxiosOptions = cloneDeep(config); + // cancelToken 如果被深拷贝,会导致最外层无法使用cancel方法来取消请求 + if (config.cancelToken) { + conf.cancelToken = config.cancelToken; + } + + if (config.signal) { + conf.signal = config.signal; + } + + const transform = this.getTransform(); + + const { requestOptions } = this.options; + + const opt: RequestOptions = Object.assign({}, requestOptions, options); + + const { beforeRequestHook, requestCatchHook, transformResponseHook } = transform || {}; + if (beforeRequestHook && isFunction(beforeRequestHook)) { + conf = beforeRequestHook(conf, opt); + } + conf.requestOptions = opt; + + conf = this.supportFormData(conf); + + return new Promise((resolve, reject) => { + this.axiosInstance + .request>(conf) + .then((res: AxiosResponse) => { + if (transformResponseHook && isFunction(transformResponseHook)) { + try { + const ret = transformResponseHook(res, opt); + resolve(ret); + } catch (err) { + reject(err || new Error('request error!')); + } + return; + } + resolve(res as unknown as Promise); + }) + .catch((e: Error | AxiosError) => { + if (requestCatchHook && isFunction(requestCatchHook)) { + reject(requestCatchHook(e, opt)); + return; + } + if (axios.isAxiosError(e)) { + // rewrite error message from axios in here + } + reject(e); + }); + }); + } +} diff --git a/src/utils/http/axios/axiosCancel.ts b/src/utils/http/axios/axiosCancel.ts new file mode 100644 index 0000000..f115ccf --- /dev/null +++ b/src/utils/http/axios/axiosCancel.ts @@ -0,0 +1,60 @@ +import type { AxiosRequestConfig } from 'axios'; + +// 用于存储每个请求的标识和取消函数 +const pendingMap = new Map(); + +const getPendingUrl = (config: AxiosRequestConfig): string => { + return [config.method, config.url].join('&'); +}; + +export class AxiosCanceler { + /** + * 添加请求 + * @param config 请求配置 + */ + public addPending(config: AxiosRequestConfig): void { + this.removePending(config); + const url = getPendingUrl(config); + const controller = new AbortController(); + config.signal = config.signal || controller.signal; + if (!pendingMap.has(url)) { + // 如果当前请求不在等待中,将其添加到等待中 + pendingMap.set(url, controller); + } + } + + /** + * 清除所有等待中的请求 + */ + public removeAllPending(): void { + pendingMap.forEach((abortController) => { + if (abortController) { + abortController.abort(); + } + }); + this.reset(); + } + + /** + * 移除请求 + * @param config 请求配置 + */ + public removePending(config: AxiosRequestConfig): void { + const url = getPendingUrl(config); + if (pendingMap.has(url)) { + // 如果当前请求在等待中,取消它并将其从等待中移除 + const abortController = pendingMap.get(url); + if (abortController) { + abortController.abort(url); + } + pendingMap.delete(url); + } + } + + /** + * 重置 + */ + public reset(): void { + pendingMap.clear(); + } +} diff --git a/src/utils/http/axios/axiosRetry.ts b/src/utils/http/axios/axiosRetry.ts new file mode 100644 index 0000000..bf44cf7 --- /dev/null +++ b/src/utils/http/axios/axiosRetry.ts @@ -0,0 +1,30 @@ +import { AxiosError, AxiosInstance } from 'axios'; +/** + * 请求重试机制 + */ + +export class AxiosRetry { + /** + * 重试 + */ + retry(axiosInstance: AxiosInstance, error: AxiosError) { + // @ts-ignore + const { config } = error.response; + const { waitTime, count } = config?.requestOptions?.retryRequest ?? {}; + config.__retryCount = config.__retryCount || 0; + if (config.__retryCount >= count) { + return Promise.reject(error); + } + config.__retryCount += 1; + //请求返回后config的header不正确造成重试请求失败,删除返回headers采用默认headers + delete config.headers; + return this.delay(waitTime).then(() => axiosInstance(config)); + } + + /** + * 延迟 + */ + private delay(waitTime: number) { + return new Promise((resolve) => setTimeout(resolve, waitTime)); + } +} diff --git a/src/utils/http/axios/axiosTransform.ts b/src/utils/http/axios/axiosTransform.ts new file mode 100644 index 0000000..5570bf0 --- /dev/null +++ b/src/utils/http/axios/axiosTransform.ts @@ -0,0 +1,57 @@ +/** + * Data processing class, can be configured according to the project + */ +import type { + AxiosInstance, + AxiosRequestConfig, + AxiosResponse, + InternalAxiosRequestConfig, +} from 'axios'; +import type { RequestOptions, Result } from '#/axios'; + +export interface CreateAxiosOptions extends AxiosRequestConfig { + authenticationScheme?: string; + transform?: AxiosTransform; + requestOptions?: RequestOptions; +} + +export abstract class AxiosTransform { + /** + * A function that is called before a request is sent. It can modify the request configuration as needed. + * 在发送请求之前调用的函数。它可以根据需要修改请求配置。 + */ + beforeRequestHook?: (config: AxiosRequestConfig, options: RequestOptions) => AxiosRequestConfig; + + /** + * @description: 处理响应数据 + */ + transformResponseHook?: (res: AxiosResponse, options: RequestOptions) => any; + + /** + * @description: 请求失败处理 + */ + requestCatchHook?: (e: Error, options: RequestOptions) => Promise; + + /** + * @description: 请求之前的拦截器 + */ + requestInterceptors?: ( + config: InternalAxiosRequestConfig, + options: CreateAxiosOptions, + ) => InternalAxiosRequestConfig; + + /** + * @description: 请求之后的拦截器 + */ + responseInterceptors?: (res: AxiosResponse) => AxiosResponse; + + /** + * @description: 请求之前的拦截器错误处理 + */ + requestInterceptorsCatch?: (error: Error) => void; + + /** + * @description: 请求之后的拦截器错误处理 + */ + responseInterceptorsCatch?: (axiosInstance: AxiosInstance, error: Error) => void; +} diff --git a/src/utils/http/axios/checkStatus.ts b/src/utils/http/axios/checkStatus.ts new file mode 100644 index 0000000..3aa292b --- /dev/null +++ b/src/utils/http/axios/checkStatus.ts @@ -0,0 +1,81 @@ +import type { ErrorMessageMode } from '#/axios'; +import { useMessage } from '@/hooks/web/useMessage'; +import { useI18n } from '@/hooks/web/useI18n'; +// import router from '@/router'; +// import { PageEnum } from '@/enums/pageEnum'; +import { useUserStoreWithOut } from '@/store/modules/user'; +import projectSetting from '@/settings/projectSetting'; +import { SessionTimeoutProcessingEnum } from '@/enums/appEnum'; + +const { createMessage, createErrorModal } = useMessage(); +const error = createMessage.error!; +const stp = projectSetting.sessionTimeoutProcessing; + +export function checkStatus( + status: number, + msg: string, + errorMessageMode: ErrorMessageMode = 'message', +): void { + const { t } = useI18n(); + const userStore = useUserStoreWithOut(); + let errMessage = ''; + + switch (status) { + case 400: + errMessage = `${msg}`; + break; + // 401: Not logged in + // Jump to the login page if not logged in, and carry the path of the current page + // Return to the current page after successful login. This step needs to be operated on the login page. + case 401: + userStore.setToken(undefined); + localStorage.setItem('X-Token', ''); + errMessage = msg || t('sys.api.errMsg401'); + if (stp === SessionTimeoutProcessingEnum.PAGE_COVERAGE) { + userStore.setSessionTimeout(true); + } else { + userStore.logout(true); + } + break; + case 403: + errMessage = t('sys.api.errMsg403'); + break; + // 404请求不存在 + case 404: + errMessage = t('sys.api.errMsg404'); + break; + case 405: + errMessage = t('sys.api.errMsg405'); + break; + case 408: + errMessage = t('sys.api.errMsg408'); + break; + case 500: + errMessage = t('sys.api.errMsg500'); + break; + case 501: + errMessage = t('sys.api.errMsg501'); + break; + case 502: + errMessage = t('sys.api.errMsg502'); + break; + case 503: + errMessage = t('sys.api.errMsg503'); + break; + case 504: + errMessage = t('sys.api.errMsg504'); + break; + case 505: + errMessage = t('sys.api.errMsg505'); + break; + default: + } + + if (errMessage) { + if (errorMessageMode === 'modal') { + createErrorModal({ title: t('sys.api.errorTip'), content: errMessage }); + } else if (errorMessageMode === 'message') { + error({ content: errMessage, key: `global_error_message_status_${status}` }); + } + } +} diff --git a/src/utils/http/axios/helper.ts b/src/utils/http/axios/helper.ts new file mode 100644 index 0000000..2e930c4 --- /dev/null +++ b/src/utils/http/axios/helper.ts @@ -0,0 +1,48 @@ +import { isObject, isString } from '@/utils/is'; + +const DATE_TIME_FORMAT = 'YYYY-MM-DD HH:mm:ss'; + +export function joinTimestamp( + join: boolean, + restful: T, +): T extends true ? string : object; + +export function joinTimestamp(join: boolean, restful = false): string | object { + if (!join) { + return restful ? '' : {}; + } + // const now = new Date().getTime(); + // if (restful) { + // return `?_t=${now}`; + // } + // return { _t: now }; +} + +/** + * @description: Format request parameter time + */ +export function formatRequestDate(params: Recordable) { + if (Object.prototype.toString.call(params) !== '[object Object]') { + return; + } + + for (const key in params) { + const format = params[key]?.format ?? null; + if (format && typeof format === 'function') { + params[key] = params[key].format(DATE_TIME_FORMAT); + } + if (isString(key)) { + const value = params[key]; + if (value) { + try { + params[key] = isString(value) ? value.trim() : value; + } catch (error: any) { + throw new Error(error); + } + } + } + if (isObject(params[key])) { + formatRequestDate(params[key]); + } + } +} diff --git a/src/utils/http/axios/index.ts b/src/utils/http/axios/index.ts new file mode 100644 index 0000000..ec4c9a9 --- /dev/null +++ b/src/utils/http/axios/index.ts @@ -0,0 +1,291 @@ +// axios配置 可自行根据项目进行更改,只需更改该文件即可,其他文件可以不动 +// The axios configuration can be changed according to the project, just change the file, other files can be left unchanged + +import type { AxiosInstance, AxiosResponse } from 'axios'; +import { clone } from 'lodash-es'; +import type { RequestOptions, Result } from '#/axios'; +import type { AxiosTransform, CreateAxiosOptions } from './axiosTransform'; +import { VAxios } from './Axios'; +import { checkStatus } from './checkStatus'; +import { useGlobSetting } from '@/hooks/setting'; +import { useMessage } from '@/hooks/web/useMessage'; +import { RequestEnum, ResultEnum, ContentTypeEnum } from '@/enums/httpEnum'; +import { isString, isUndefined, isNull, isEmpty } from '@/utils/is'; +import { getToken } from '@/utils/auth'; +import { setObjToUrlParams, deepMerge } from '@/utils'; +import { useErrorLogStoreWithOut } from '@/store/modules/errorLog'; +import { useI18n } from '@/hooks/web/useI18n'; +import { joinTimestamp, formatRequestDate } from './helper'; +import { useUserStoreWithOut } from '@/store/modules/user'; +import { AxiosRetry } from '@/utils/http/axios/axiosRetry'; +import axios from 'axios'; + +const globSetting = useGlobSetting(); +const urlPrefix = globSetting.urlPrefix; +const { createMessage, createErrorModal, createSuccessModal } = useMessage(); + +/** + * @description: 数据处理,方便区分多种处理方式 + */ +const transform: AxiosTransform = { + /** + * @description: 处理响应数据。如果数据不是预期格式,可直接抛出错误 + */ + transformResponseHook: (res: AxiosResponse, options: RequestOptions) => { + const { t } = useI18n(); + const { isTransformResponse, isReturnNativeResponse } = options; + // 是否返回原生响应头 比如:需要获取响应头时使用该属性 + if (isReturnNativeResponse) { + return res; + } + // 不进行任何处理,直接返回 + // 用于页面代码可能需要直接获取code,data,message这些信息时开启 + if (!isTransformResponse) { + return res.data; + } + // 错误的时候返回 + const { data } = res; + + if (!data) { + // return '[HTTP] Request has no return value'; + throw new Error(t('sys.api.apiRequestFailed')); + } + if (!data.code && !data.result) { + return data; + } + // 这里 code,result,message为 后台统一的字段,需要在 types.ts内修改为项目自己的接口返回格式 + const { code, result, message } = data; + // 这里逻辑可以根据项目进行修改 + const hasSuccess = data && Reflect.has(data, 'code') && code === ResultEnum.SUCCESS; + if (hasSuccess) { + let successMsg = message; + + if (isNull(successMsg) || isUndefined(successMsg) || isEmpty(successMsg)) { + successMsg = t(`sys.api.operationSuccess`); + } + + if (options.successMessageMode === 'modal') { + createSuccessModal({ title: t('sys.api.successTip'), content: successMsg }); + } else if (options.successMessageMode === 'message') { + createMessage.success(successMsg); + } + return result; + } + + // 在此处根据自己项目的实际情况对不同的code执行不同的操作 + // 如果不希望中断当前请求,请return数据,否则直接抛出异常即可 + let timeoutMsg = ''; + switch (code) { + case ResultEnum.TIMEOUT: + timeoutMsg = t('sys.api.timeoutMessage'); + const userStore = useUserStoreWithOut(); + userStore.logout(true); + break; + default: + if (message) { + timeoutMsg = message; + } + } + + // errorMessageMode='modal'的时候会显示modal错误弹窗,而不是消息提示,用于一些比较重要的错误 + // errorMessageMode='none' 一般是调用时明确表示不希望自动弹出错误提示 + if (options.errorMessageMode === 'modal') { + createErrorModal({ title: t('sys.api.errorTip'), content: timeoutMsg }); + } else if (options.errorMessageMode === 'message') { + createMessage.error(timeoutMsg); + } + + throw new Error(timeoutMsg || t('sys.api.apiRequestFailed')); + }, + + // 请求之前处理config + beforeRequestHook: (config, options) => { + const { apiUrl, joinPrefix, joinParamsToUrl, formatDate, joinTime = true, urlPrefix } = options; + + if (joinPrefix) { + config.url = `${urlPrefix}${config.url}`; + } + + if (apiUrl && isString(apiUrl)) { + config.url = `${apiUrl}${config.url}`; + } + const params = config.params || {}; + const data = config.data || false; + formatDate && data && !isString(data) && formatRequestDate(data); + if (config.method?.toUpperCase() === RequestEnum.GET) { + if (!isString(params)) { + // 给 get 请求加上时间戳参数,避免从缓存中拿数据。 + config.params = Object.assign(params || {}, joinTimestamp(joinTime, false)); + } else { + // 兼容restful风格 + config.url = config.url + params + `${joinTimestamp(joinTime, true)}`; + config.params = undefined; + } + } else { + if (!isString(params)) { + formatDate && formatRequestDate(params); + if ( + Reflect.has(config, 'data') && + config.data && + (Object.keys(config.data).length > 0 || config.data instanceof FormData) + ) { + config.data = data; + config.params = params; + } else { + // 非GET请求如果没有提供data,则将params视为data + config.data = params; + config.params = undefined; + } + if (joinParamsToUrl) { + config.url = setObjToUrlParams( + config.url as string, + Object.assign({}, config.params, config.data), + ); + } + } else { + // 兼容restful风格 + config.url = config.url + params; + config.params = undefined; + } + } + return config; + }, + + /** + * @description: 请求拦截器处理 + */ + requestInterceptors: (config, options) => { + // 请求之前处理config + const token = getToken(); + if (token && (config as Recordable)?.requestOptions?.withToken !== false) { + // jwt token + (config as Recordable).headers.Authorization = options.authenticationScheme + ? `${options.authenticationScheme} ${token}` + : token; + config.headers['X-Token'] = token; + } + return config; + }, + + /** + * @description: 响应拦截器处理 + */ + responseInterceptors: (res: AxiosResponse) => { + return res; + }, + + /** + * @description: 响应错误处理 + */ + responseInterceptorsCatch: (axiosInstance: AxiosInstance, error: any) => { + const { t } = useI18n(); + const errorLogStore = useErrorLogStoreWithOut(); + errorLogStore.addAjaxErrorInfo(error); + const { response, code, message, config } = error || {}; + const errorMessageMode = config?.requestOptions?.errorMessageMode || 'none'; + const msg: string = response?.data?.error?.message ?? ''; + const err: string = error?.toString?.() ?? ''; + let errMessage = ''; + + if (axios.isCancel(error)) { + return Promise.reject(error); + } + + try { + if (code === 'ECONNABORTED' && message.indexOf('timeout') !== -1) { + errMessage = t('sys.api.apiTimeoutMessage'); + } + if (err?.includes('Network Error')) { + errMessage = t('sys.api.networkExceptionMsg'); + } + + if (errMessage) { + if (errorMessageMode === 'modal') { + createErrorModal({ title: t('sys.api.errorTip'), content: errMessage }); + } else if (errorMessageMode === 'message') { + createMessage.error(errMessage); + } + return Promise.reject(error); + } + } catch (error) { + throw new Error(error as unknown as string); + } + + checkStatus(error?.response?.status, msg, errorMessageMode); + + // 添加自动重试机制 保险起见 只针对GET请求 + const retryRequest = new AxiosRetry(); + const { isOpenRetry } = config.requestOptions.retryRequest; + config.method?.toUpperCase() === RequestEnum.GET && + isOpenRetry && + // @ts-ignore + retryRequest.retry(axiosInstance, error); + return Promise.reject(error); + }, +}; + +function createAxios(opt?: Partial) { + return new VAxios( + // 深度合并 + deepMerge( + { + // See https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication#authentication_schemes + // authentication schemes,e.g: Bearer + // authenticationScheme: 'Bearer', + authenticationScheme: '', + timeout: 30 * 1000, + // 基础接口地址 + // baseURL: globSetting.apiUrl, + + headers: { + 'Content-Type': ContentTypeEnum.JSON, + 'T-Token': getToken(), + }, + // 如果是form-data格式 + // headers: { 'Content-Type': ContentTypeEnum.FORM_URLENCODED }, + // 数据处理方式 + transform: clone(transform), + // 配置项,下面的选项都可以在独立的接口请求中覆盖 + requestOptions: { + // 默认将prefix 添加到url + joinPrefix: true, + // 是否返回原生响应头 比如:需要获取响应头时使用该属性 + isReturnNativeResponse: false, + // 需要对返回数据进行处理 + isTransformResponse: true, + // post请求的时候添加参数到url + joinParamsToUrl: false, + // 格式化提交参数时间 + formatDate: true, + // 消息提示类型 + errorMessageMode: 'message', + // 接口地址 + apiUrl: globSetting.apiUrl, + // 接口拼接地址 + urlPrefix: urlPrefix, + // 是否加入时间戳 + joinTime: true, + // 忽略重复请求 + ignoreCancelToken: true, + // 是否携带token + withToken: true, + retryRequest: { + isOpenRetry: true, + count: 5, + waitTime: 100, + }, + }, + }, + opt || {}, + ), + ); +} +export const defHttp = createAxios(); + +// other api url +// export const otherHttp = createAxios({ +// requestOptions: { +// apiUrl: 'xxx', +// urlPrefix: 'xxx', +// }, +// }); diff --git a/src/utils/index.ts b/src/utils/index.ts new file mode 100644 index 0000000..531ef7b --- /dev/null +++ b/src/utils/index.ts @@ -0,0 +1,147 @@ +import type { RouteLocationNormalized, RouteRecordNormalized } from 'vue-router'; +import type { App, Component } from 'vue'; + +import { intersectionWith, isEqual, mergeWith, unionWith } from 'lodash-es'; +import { unref } from 'vue'; +import { isArray, isObject } from '@/utils/is'; + +export const noop = () => {}; + +/** + * @description: Set ui mount node + */ +export function getPopupContainer(node?: HTMLElement): HTMLElement { + return (node?.parentNode as HTMLElement) ?? document.body; +} + +/** + * Add the object as a parameter to the URL + * @param baseUrl url + * @param obj + * @returns {string} + * eg: + * let obj = {a: '3', b: '4'} + * setObjToUrlParams('www.baidu.com', obj) + * ==>www.baidu.com?a=3&b=4 + */ +export function setObjToUrlParams(baseUrl: string, obj: any): string { + let parameters = ''; + for (const key in obj) { + parameters += key + '=' + encodeURIComponent(obj[key]) + '&'; + } + parameters = parameters.replace(/&$/, ''); + return /\?$/.test(baseUrl) ? baseUrl + parameters : baseUrl.replace(/\/?$/, '?') + parameters; +} + +/** + * Recursively merge two objects. + * 递归合并两个对象。 + * + * @param source The source object to merge from. 要合并的源对象。 + * @param target The target object to merge into. 目标对象,合并后结果存放于此。 + * @param mergeArrays How to merge arrays. Default is "replace". + * 如何合并数组。默认为replace。 + * - "union": Union the arrays. 对数组执行并集操作。 + * - "intersection": Intersect the arrays. 对数组执行交集操作。 + * - "concat": Concatenate the arrays. 连接数组。 + * - "replace": Replace the source array with the target array. 用目标数组替换源数组。 + * @returns The merged object. 合并后的对象。 + */ +export function deepMerge( + source: T, + target: U, + mergeArrays: 'union' | 'intersection' | 'concat' | 'replace' = 'replace', +): T & U { + if (!target) { + return source as T & U; + } + if (!source) { + return target as T & U; + } + return mergeWith({}, source, target, (sourceValue, targetValue) => { + if (isArray(targetValue) && isArray(sourceValue)) { + switch (mergeArrays) { + case 'union': + return unionWith(sourceValue, targetValue, isEqual); + case 'intersection': + return intersectionWith(sourceValue, targetValue, isEqual); + case 'concat': + return sourceValue.concat(targetValue); + case 'replace': + return targetValue; + default: + throw new Error(`Unknown merge array strategy: ${mergeArrays as string}`); + } + } + if (isObject(targetValue) && isObject(sourceValue)) { + return deepMerge(sourceValue, targetValue, mergeArrays); + } + return undefined; + }); +} + +export function openWindow( + url: string, + opt?: { target?: TargetContext | string; noopener?: boolean; noreferrer?: boolean }, +) { + const { target = '__blank', noopener = true, noreferrer = true } = opt || {}; + const feature: string[] = []; + + noopener && feature.push('noopener=yes'); + noreferrer && feature.push('noreferrer=yes'); + + window.open(url, target, feature.join(',')); +} + +// dynamic use hook props +export function getDynamicProps, U>(props: T): Partial { + const ret: Recordable = {}; + + Object.keys(props).map((key) => { + ret[key] = unref((props as Recordable)[key]); + }); + + return ret as Partial; +} + +export function 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[], + }; +} + +// https://github.com/vant-ui/vant/issues/8302 +type EventShim = { + new (...args: any[]): { + $props: { + onClick?: (...args: any[]) => void; + }; + }; +}; + +export type WithInstall = T & { + install(app: App): void; +} & EventShim; + +export type CustomComponent = Component & { displayName?: string }; + +export const withInstall = (component: T, alias?: string) => { + (component as Record).install = (app: App) => { + const compName = component.name || component.displayName; + if (!compName) return; + app.component(compName, component); + if (alias) { + app.config.globalProperties[alias] = component; + } + }; + return component as WithInstall; +}; diff --git a/src/utils/is.ts b/src/utils/is.ts new file mode 100644 index 0000000..97c2ea9 --- /dev/null +++ b/src/utils/is.ts @@ -0,0 +1,72 @@ +export { + isArguments, + isArrayBuffer, + isArrayLike, + isArrayLikeObject, + isBuffer, + isBoolean, + isDate, + isElement, + isEmpty, + isEqual, + isEqualWith, + isError, + isFunction, + isFinite, + isLength, + isMap, + isMatch, + isMatchWith, + isNative, + isNil, + isNumber, + isNull, + isObjectLike, + isPlainObject, + isRegExp, + isSafeInteger, + isSet, + isString, + isSymbol, + isTypedArray, + isUndefined, + isWeakMap, + isWeakSet, +} from 'lodash-es'; +const toString = Object.prototype.toString; + +export function is(val: unknown, type: string) { + return toString.call(val) === `[object ${type}]`; +} + +export function isDef(val?: T): val is T { + return typeof val !== 'undefined'; +} + +// TODO 此处 isObject 存在歧义 +export function isObject(val: any): val is Record { + return val !== null && is(val, 'Object'); +} + +// TODO 此处 isArray 存在歧义 +export function isArray(val: any): val is Array { + return val && Array.isArray(val); +} + +export function isWindow(val: any): val is Window { + return typeof window !== 'undefined' && is(val, 'Window'); +} + +export const isServer = typeof window === 'undefined'; + +export const isClient = !isServer; + +export function isHttpUrl(path: string): boolean { + const reg = /^http(s)?:\/\/([\w-]+\.)+[\w-]+(\/[\w- ./?%&=]*)?/; + return reg.test(path); +} + +export function isPascalCase(str: string): boolean { + const regex = /^[A-Z][A-Za-z]*$/; + return regex.test(str); +} diff --git a/src/utils/lib/echarts.ts b/src/utils/lib/echarts.ts new file mode 100644 index 0000000..e1f95cd --- /dev/null +++ b/src/utils/lib/echarts.ts @@ -0,0 +1,57 @@ +import * as echarts from 'echarts/core'; + +import { + BarChart, + LineChart, + PieChart, + MapChart, + PictorialBarChart, + RadarChart, + ScatterChart, +} from 'echarts/charts'; + +import { + TitleComponent, + TooltipComponent, + GridComponent, + PolarComponent, + AriaComponent, + ParallelComponent, + LegendComponent, + RadarComponent, + ToolboxComponent, + DataZoomComponent, + VisualMapComponent, + TimelineComponent, + CalendarComponent, + GraphicComponent, +} from 'echarts/components'; + +import { SVGRenderer } from 'echarts/renderers'; + +echarts.use([ + LegendComponent, + TitleComponent, + TooltipComponent, + GridComponent, + PolarComponent, + AriaComponent, + ParallelComponent, + BarChart, + LineChart, + PieChart, + MapChart, + RadarChart, + SVGRenderer, + PictorialBarChart, + RadarComponent, + ToolboxComponent, + DataZoomComponent, + VisualMapComponent, + TimelineComponent, + CalendarComponent, + GraphicComponent, + ScatterChart, +]); + +export default echarts; diff --git a/src/utils/log.ts b/src/utils/log.ts new file mode 100644 index 0000000..8f79800 --- /dev/null +++ b/src/utils/log.ts @@ -0,0 +1,9 @@ +const projectName = import.meta.env.VITE_GLOB_APP_TITLE; + +export function warn(message: string) { + console.warn(`[${projectName} warn]:${message}`); +} + +export function error(message: string) { + throw new Error(`[${projectName} error]:${message}`); +} diff --git a/src/utils/mitt.ts b/src/utils/mitt.ts new file mode 100644 index 0000000..cf09fd8 --- /dev/null +++ b/src/utils/mitt.ts @@ -0,0 +1,122 @@ +/** + * copy to https://github.com/developit/mitt + * Expand clear method + */ +export type EventType = string | symbol; + +// An event handler can take an optional event argument +// and should not return a value +export type Handler = (event: T) => void; +export type WildcardHandler> = ( + type: keyof T, + event: T[keyof T], +) => void; + +// An array of all currently registered event handlers for a type +export type EventHandlerList = Array>; +export type WildCardEventHandlerList> = Array>; + +// A map of event types and their corresponding event handlers. +export type EventHandlerMap> = Map< + keyof Events | '*', + EventHandlerList | WildCardEventHandlerList +>; + +export interface Emitter> { + all: EventHandlerMap; + + on(type: Key, handler: Handler): void; + on(type: '*', handler: WildcardHandler): void; + + off(type: Key, handler?: Handler): void; + off(type: '*', handler: WildcardHandler): void; + + emit(type: Key, event: Events[Key]): void; + emit(type: undefined extends Events[Key] ? Key : never): void; + clear(): void; +} + +/** + * Mitt: Tiny (~200b) functional event emitter / pubsub. + * @name mitt + * @returns {Mitt} + */ +export function mitt>( + all?: EventHandlerMap, +): Emitter { + type GenericEventHandler = Handler | WildcardHandler; + all = all || new Map(); + + return { + /** + * A Map of event names to registered handler functions. + */ + all, + + /** + * Register an event handler for the given type. + * @param {string|symbol} type Type of event to listen for, or `'*'` for all events + * @param {Function} handler Function to call in response to given event + * @memberOf mitt + */ + on(type: Key, handler: GenericEventHandler) { + const handlers: Array | undefined = all!.get(type); + if (handlers) { + handlers.push(handler); + } else { + all!.set(type, [handler] as EventHandlerList); + } + }, + + /** + * Remove an event handler for the given type. + * If `handler` is omitted, all handlers of the given type are removed. + * @param {string|symbol} type Type of event to unregister `handler` from (`'*'` to remove a wildcard handler) + * @param {Function} [handler] Handler function to remove + * @memberOf mitt + */ + off(type: Key, handler?: GenericEventHandler) { + const handlers: Array | undefined = all!.get(type); + if (handlers) { + if (handler) { + handlers.splice(handlers.indexOf(handler) >>> 0, 1); + } else { + all!.set(type, []); + } + } + }, + + /** + * Invoke all handlers for the given type. + * If present, `'*'` handlers are invoked after type-matched handlers. + * + * Note: Manually firing '*' handlers is not supported. + * + * @param {string|symbol} type The event type to invoke + * @param {Any} [evt] Any value (object is recommended and powerful), passed to each handler + * @memberOf mitt + */ + emit(type: Key, evt?: Events[Key]) { + let handlers = all!.get(type); + if (handlers) { + (handlers as EventHandlerList).slice().forEach((handler) => { + handler(evt as Events[Key]); + }); + } + + handlers = all!.get('*'); + if (handlers) { + (handlers as WildCardEventHandlerList).slice().forEach((handler) => { + handler(type, evt as Events[Key]); + }); + } + }, + + /** + * Clear all + */ + clear() { + this.all.clear(); + }, + }; +} diff --git a/src/utils/propTypes.ts b/src/utils/propTypes.ts new file mode 100644 index 0000000..b4f0623 --- /dev/null +++ b/src/utils/propTypes.ts @@ -0,0 +1,35 @@ +import { CSSProperties, VNodeChild } from 'vue'; +import { createTypes, VueTypeValidableDef, VueTypesInterface, toValidableType } from 'vue-types'; + +export type VueNode = VNodeChild | JSX.Element; + +type PropTypes = VueTypesInterface & { + readonly style: VueTypeValidableDef; + readonly VNodeChild: VueTypeValidableDef; + // readonly trueBool: VueTypeValidableDef; +}; +const newPropTypes = createTypes({ + func: undefined, + bool: undefined, + string: undefined, + number: undefined, + object: undefined, + integer: undefined, +}) as PropTypes; + +// 从 vue-types v5.0 开始,extend()方法已经废弃,当前已改为官方推荐的ES6+方法 https://dwightjack.github.io/vue-types/advanced/extending-vue-types.html#the-extend-method +class propTypes extends newPropTypes { + // a native-like validator that supports the `.validable` method + static override get style() { + return toValidableType('style', { + type: [String, Object], + }); + } + + static override get VNodeChild() { + return toValidableType('VNodeChild', { + type: undefined, + }); + } +} +export { propTypes }; diff --git a/src/utils/props.ts b/src/utils/props.ts new file mode 100644 index 0000000..32c8ba6 --- /dev/null +++ b/src/utils/props.ts @@ -0,0 +1,185 @@ +// copy from element-plus + +import { warn } from 'vue'; +import { fromPairs, isObject } from 'lodash-es'; +import type { ExtractPropTypes, PropType } from 'vue'; +import type { Mutable } from './types'; + +const wrapperKey = Symbol(); +export type PropWrapper = { [wrapperKey]: T }; + +export const propKey = Symbol(); + +type ResolveProp = ExtractPropTypes<{ + key: { type: T; required: true }; +}>['key']; +type ResolvePropType = ResolveProp extends { type: infer V } ? V : ResolveProp; +type ResolvePropTypeWithReadonly = Readonly extends Readonly> + ? ResolvePropType + : ResolvePropType; + +type IfUnknown = [unknown] extends [T] ? V : T; + +export type BuildPropOption, R, V, C> = { + type?: T; + values?: readonly V[]; + required?: R; + default?: R extends true + ? never + : D extends Record | Array + ? () => D + : (() => D) | D; + validator?: ((val: any) => val is C) | ((val: any) => boolean); +}; + +type _BuildPropType = + | (T extends PropWrapper + ? T[typeof wrapperKey] + : [V] extends [never] + ? ResolvePropTypeWithReadonly + : never) + | V + | C; +export type BuildPropType = _BuildPropType< + IfUnknown, + IfUnknown, + IfUnknown +>; + +type _BuildPropDefault = [T] extends [ + // eslint-disable-next-line @typescript-eslint/ban-types + Record | Array | Function, +] + ? D + : D extends () => T + ? ReturnType + : D; + +export type BuildPropDefault = R extends true + ? { readonly default?: undefined } + : { + readonly default: Exclude extends never + ? undefined + : Exclude<_BuildPropDefault, undefined>; + }; +export type BuildPropReturn = { + readonly type: PropType>; + readonly required: IfUnknown; + readonly validator: ((val: unknown) => boolean) | undefined; + [propKey]: true; +} & BuildPropDefault, IfUnknown, IfUnknown>; + +/** + * @description Build prop. It can better optimize prop types + * @description 生成 prop,能更好地优化类型 + * @example + // limited options + // the type will be PropType<'light' | 'dark'> + buildProp({ + type: String, + values: ['light', 'dark'], + } as const) + * @example + // limited options and other types + // the type will be PropType<'small' | 'medium' | number> + buildProp({ + type: [String, Number], + values: ['small', 'medium'], + validator: (val: unknown): val is number => typeof val === 'number', + } as const) + @link see more: https://github.com/element-plus/element-plus/pull/3341 + */ +export function buildProp< + T = never, + D extends BuildPropType = never, + R extends boolean = false, + V = never, + C = never, +>(option: BuildPropOption, key?: string): BuildPropReturn { + // filter native prop type and nested prop, e.g `null`, `undefined` (from `buildProps`) + if (!isObject(option) || !!option[propKey]) return option as any; + + const { values, required, default: defaultValue, type, validator } = option; + + const _validator = + values || validator + ? (val: unknown) => { + let valid = false; + let allowedValues: unknown[] = []; + + if (values) { + allowedValues = [...values, defaultValue]; + valid ||= allowedValues.includes(val); + } + if (validator) valid ||= validator(val); + + if (!valid && allowedValues.length > 0) { + const allowValuesText = [...new Set(allowedValues)] + .map((value) => JSON.stringify(value)) + .join(', '); + warn( + `Invalid prop: validation failed${ + key ? ` for prop "${key}"` : '' + }. Expected one of [${allowValuesText}], got value ${JSON.stringify(val)}.`, + ); + } + return valid; + } + : undefined; + + return { + type: + typeof type === 'object' && Object.getOwnPropertySymbols(type).includes(wrapperKey) && type + ? type[wrapperKey] + : type, + required: !!required, + default: defaultValue, + validator: _validator, + [propKey]: true, + } as unknown as BuildPropReturn; +} + +type NativePropType = [((...args: any) => any) | { new (...args: any): any } | undefined | null]; + +export const buildProps = < + O extends { + [K in keyof O]: O[K] extends BuildPropReturn + ? O[K] + : [O[K]] extends NativePropType + ? O[K] + : O[K] extends BuildPropOption + ? D extends BuildPropType + ? BuildPropOption + : never + : never; + }, +>( + props: O, +) => + fromPairs( + Object.entries(props).map(([key, option]) => [key, buildProp(option as any, key)]), + ) as unknown as { + [K in keyof O]: O[K] extends { [propKey]: boolean } + ? O[K] + : [O[K]] extends NativePropType + ? O[K] + : O[K] extends BuildPropOption< + infer T, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + infer _D, + infer R, + infer V, + infer C + > + ? BuildPropReturn + : never; + }; + +export const definePropType = (val: any) => ({ [wrapperKey]: val }) as PropWrapper; + +export const keyOf = (arr: T) => Object.keys(arr) as Array; + +export const mutable = >(val: T) => + val as Mutable; + +export const componentSize = ['large', 'medium', 'small', 'mini'] as const; diff --git a/src/utils/signalR.ts b/src/utils/signalR.ts new file mode 100644 index 0000000..3b9b68a --- /dev/null +++ b/src/utils/signalR.ts @@ -0,0 +1,10 @@ +import * as signalR from '@microsoft/signalr'; +import { getAppEnvConfig } from '@/utils/env'; + +const { VITE_GLOB_API_URL } = getAppEnvConfig(); +console.log(VITE_GLOB_API_URL); +export const signal = new signalR.HubConnectionBuilder() + .withUrl(VITE_GLOB_API_URL + '/chathub') + // .withAutomaticReconnect([0, 2000, 10000, 30000]) + // .configureLogging(signalR.LogLevel.Information) + .build(); diff --git a/src/utils/types.ts b/src/utils/types.ts new file mode 100644 index 0000000..7c50e7f --- /dev/null +++ b/src/utils/types.ts @@ -0,0 +1,65 @@ +// copy from element-plus + +import type { CSSProperties, Plugin } from 'vue'; + +type OptionalKeys> = { + [K in keyof T]: T extends Record ? never : K; +}[keyof T]; + +type RequiredKeys> = Exclude>; + +type MonoArgEmitter = (evt: K, arg?: T[K]) => void; + +type BiArgEmitter = (evt: K, arg: T[K]) => void; + +export type EventEmitter> = MonoArgEmitter> & + BiArgEmitter>; + +export type AnyFunction = (...args: any[]) => T; + +export type PartialReturnType unknown> = Partial>; + +export type SFCWithInstall = T & Plugin; + +export type Nullable = T | null; + +export type RefElement = Nullable; + +export type CustomizedHTMLElement = HTMLElement & T; + +export type Indexable = { + [key: string]: T; +}; + +export type Hash = Indexable; + +export type TimeoutHandle = ReturnType; + +export type ComponentSize = 'large' | 'medium' | 'small' | 'mini'; + +export type StyleValue = string | CSSProperties | Array; + +export type Mutable = { -readonly [P in keyof T]: T[P] }; + +export type Merge = { + [K in keyof O | keyof T]: K extends keyof T ? T[K] : K extends keyof O ? O[K] : never; +}; + +/** + * T = [ + * { name: string; age: number; }, + * { sex: 'male' | 'female'; age: string } + * ] + * => + * MergeAll = { + * name: string; + * sex: 'male' | 'female'; + * age: string + * } + */ +export type MergeAll = T extends [ + infer F extends object, + ...infer Rest extends object[], +] + ? MergeAll> + : R; diff --git a/src/utils/uuid.ts b/src/utils/uuid.ts new file mode 100644 index 0000000..934b9f0 --- /dev/null +++ b/src/utils/uuid.ts @@ -0,0 +1,42 @@ +const hexList: string[] = []; +for (let i = 0; i <= 15; i++) { + hexList[i] = i.toString(16); +} +export function buildGUID(): string { + let guid = ''; + for (let i = 1; i <= 36; i++) { + if (i === 9 || i === 14 || i === 19 || i === 24) { + guid += '-'; + } else if (i === 15) { + guid += 4; + } else if (i === 20) { + guid += hexList[(Math.random() * 4) | 8]; + } else { + guid += hexList[(Math.random() * 16) | 0]; + } + } + return guid; +} +export function buildUUID(): string { + let uuid = ''; + for (let i = 1; i <= 36; i++) { + if (i === 9 || i === 14 || i === 19 || i === 24) { + uuid += '-'; + } else if (i === 15) { + uuid += 4; + } else if (i === 20) { + uuid += hexList[(Math.random() * 4) | 8]; + } else { + uuid += hexList[(Math.random() * 16) | 0]; + } + } + return uuid.replace(/-/g, ''); +} + +let unique = 0; +export function buildShortUUID(prefix = ''): string { + const time = Date.now(); + const random = Math.floor(Math.random() * 1000000000); + unique++; + return prefix + '_' + random + unique + String(time); +} diff --git a/src/views/dashboard/analysis/components/VisitSource.vue b/src/views/dashboard/analysis/components/VisitSource.vue new file mode 100644 index 0000000..56a2e31 --- /dev/null +++ b/src/views/dashboard/analysis/components/VisitSource.vue @@ -0,0 +1,82 @@ + + diff --git a/src/views/dashboard/analysis/index.vue b/src/views/dashboard/analysis/index.vue new file mode 100644 index 0000000..ef192ba --- /dev/null +++ b/src/views/dashboard/analysis/index.vue @@ -0,0 +1,99 @@ + + diff --git a/src/views/dashboard/test/ResourceMenu/Resource/index.vue b/src/views/dashboard/test/ResourceMenu/Resource/index.vue new file mode 100644 index 0000000..897bff8 --- /dev/null +++ b/src/views/dashboard/test/ResourceMenu/Resource/index.vue @@ -0,0 +1,66 @@ + + + + + diff --git a/src/views/dashboard/test/ResourceMenu/index.vue b/src/views/dashboard/test/ResourceMenu/index.vue new file mode 100644 index 0000000..b8a77a7 --- /dev/null +++ b/src/views/dashboard/test/ResourceMenu/index.vue @@ -0,0 +1,71 @@ + + + + + diff --git a/src/views/dashboard/test/SearchMenu/Camera/index.vue b/src/views/dashboard/test/SearchMenu/Camera/index.vue new file mode 100644 index 0000000..3e6a43a --- /dev/null +++ b/src/views/dashboard/test/SearchMenu/Camera/index.vue @@ -0,0 +1,27 @@ + + + + + diff --git a/src/views/dashboard/test/SearchMenu/CloudQueryModal/01B759D0-567B-4794-9386-645E7DC93C5F.png b/src/views/dashboard/test/SearchMenu/CloudQueryModal/01B759D0-567B-4794-9386-645E7DC93C5F.png new file mode 100644 index 0000000..62d78fa Binary files /dev/null and b/src/views/dashboard/test/SearchMenu/CloudQueryModal/01B759D0-567B-4794-9386-645E7DC93C5F.png differ diff --git a/src/views/dashboard/test/SearchMenu/CloudQueryModal/53E2647B-EF88-4793-9BFE-281F3EDD2BC7.png b/src/views/dashboard/test/SearchMenu/CloudQueryModal/53E2647B-EF88-4793-9BFE-281F3EDD2BC7.png new file mode 100644 index 0000000..94cb916 Binary files /dev/null and b/src/views/dashboard/test/SearchMenu/CloudQueryModal/53E2647B-EF88-4793-9BFE-281F3EDD2BC7.png differ diff --git a/src/views/dashboard/test/SearchMenu/CloudQueryModal/AdvancedQuery/index.vue b/src/views/dashboard/test/SearchMenu/CloudQueryModal/AdvancedQuery/index.vue new file mode 100644 index 0000000..c4c482c --- /dev/null +++ b/src/views/dashboard/test/SearchMenu/CloudQueryModal/AdvancedQuery/index.vue @@ -0,0 +1,77 @@ + + + + + diff --git a/src/views/dashboard/test/SearchMenu/CloudQueryModal/BasicFarmland/index.vue b/src/views/dashboard/test/SearchMenu/CloudQueryModal/BasicFarmland/index.vue new file mode 100644 index 0000000..08004fb --- /dev/null +++ b/src/views/dashboard/test/SearchMenu/CloudQueryModal/BasicFarmland/index.vue @@ -0,0 +1,71 @@ + + + + + diff --git a/src/views/dashboard/test/SearchMenu/CloudQueryModal/BasicQuery/ModalMap/index.vue b/src/views/dashboard/test/SearchMenu/CloudQueryModal/BasicQuery/ModalMap/index.vue new file mode 100644 index 0000000..23eabb8 --- /dev/null +++ b/src/views/dashboard/test/SearchMenu/CloudQueryModal/BasicQuery/ModalMap/index.vue @@ -0,0 +1,37 @@ + + + + + diff --git a/src/views/dashboard/test/SearchMenu/CloudQueryModal/BasicQuery/index.vue b/src/views/dashboard/test/SearchMenu/CloudQueryModal/BasicQuery/index.vue new file mode 100644 index 0000000..29cbc7a --- /dev/null +++ b/src/views/dashboard/test/SearchMenu/CloudQueryModal/BasicQuery/index.vue @@ -0,0 +1,154 @@ + + + + + diff --git a/src/views/dashboard/test/SearchMenu/CloudQueryModal/HistoryPhoto/index.vue b/src/views/dashboard/test/SearchMenu/CloudQueryModal/HistoryPhoto/index.vue new file mode 100644 index 0000000..5fc90b4 --- /dev/null +++ b/src/views/dashboard/test/SearchMenu/CloudQueryModal/HistoryPhoto/index.vue @@ -0,0 +1,163 @@ + + + + + diff --git a/src/views/dashboard/test/SearchMenu/CloudQueryModal/HistoryYearNow/index.vue b/src/views/dashboard/test/SearchMenu/CloudQueryModal/HistoryYearNow/index.vue new file mode 100644 index 0000000..08004fb --- /dev/null +++ b/src/views/dashboard/test/SearchMenu/CloudQueryModal/HistoryYearNow/index.vue @@ -0,0 +1,71 @@ + + + + + diff --git a/src/views/dashboard/test/SearchMenu/CloudQueryModal/MultiYearNow/index.vue b/src/views/dashboard/test/SearchMenu/CloudQueryModal/MultiYearNow/index.vue new file mode 100644 index 0000000..08004fb --- /dev/null +++ b/src/views/dashboard/test/SearchMenu/CloudQueryModal/MultiYearNow/index.vue @@ -0,0 +1,71 @@ + + + + + diff --git a/src/views/dashboard/test/SearchMenu/CloudQueryModal/MultiYearProject/index.vue b/src/views/dashboard/test/SearchMenu/CloudQueryModal/MultiYearProject/index.vue new file mode 100644 index 0000000..08004fb --- /dev/null +++ b/src/views/dashboard/test/SearchMenu/CloudQueryModal/MultiYearProject/index.vue @@ -0,0 +1,71 @@ + + + + + diff --git a/src/views/dashboard/test/SearchMenu/CloudQueryModal/TimeImages/index.vue b/src/views/dashboard/test/SearchMenu/CloudQueryModal/TimeImages/index.vue new file mode 100644 index 0000000..47abda2 --- /dev/null +++ b/src/views/dashboard/test/SearchMenu/CloudQueryModal/TimeImages/index.vue @@ -0,0 +1,71 @@ + + + + + diff --git a/src/views/dashboard/test/SearchMenu/CloudQueryModal/index.vue b/src/views/dashboard/test/SearchMenu/CloudQueryModal/index.vue new file mode 100644 index 0000000..4688e28 --- /dev/null +++ b/src/views/dashboard/test/SearchMenu/CloudQueryModal/index.vue @@ -0,0 +1,34 @@ + + + + + diff --git a/src/views/dashboard/test/SearchMenu/Satellite/index.vue b/src/views/dashboard/test/SearchMenu/Satellite/index.vue new file mode 100644 index 0000000..edb2e87 --- /dev/null +++ b/src/views/dashboard/test/SearchMenu/Satellite/index.vue @@ -0,0 +1,71 @@ + + + + + diff --git a/src/views/dashboard/test/SearchMenu/Search/index.vue b/src/views/dashboard/test/SearchMenu/Search/index.vue new file mode 100644 index 0000000..1e2baff --- /dev/null +++ b/src/views/dashboard/test/SearchMenu/Search/index.vue @@ -0,0 +1,119 @@ + + + + + diff --git a/src/views/dashboard/test/SearchMenu/index.vue b/src/views/dashboard/test/SearchMenu/index.vue new file mode 100644 index 0000000..86e020d --- /dev/null +++ b/src/views/dashboard/test/SearchMenu/index.vue @@ -0,0 +1,155 @@ + + + + + diff --git a/src/views/dashboard/test/components/ShowImage/index.vue b/src/views/dashboard/test/components/ShowImage/index.vue new file mode 100644 index 0000000..0dbff89 --- /dev/null +++ b/src/views/dashboard/test/components/ShowImage/index.vue @@ -0,0 +1,52 @@ + + + + + diff --git a/src/views/dashboard/test/components/ShowTableList/index.vue b/src/views/dashboard/test/components/ShowTableList/index.vue new file mode 100644 index 0000000..60b3a37 --- /dev/null +++ b/src/views/dashboard/test/components/ShowTableList/index.vue @@ -0,0 +1,138 @@ + + + + diff --git a/src/views/dashboard/test/components/SubTitleSelect/index.vue b/src/views/dashboard/test/components/SubTitleSelect/index.vue new file mode 100644 index 0000000..dfb4b4e --- /dev/null +++ b/src/views/dashboard/test/components/SubTitleSelect/index.vue @@ -0,0 +1,35 @@ + + + + + diff --git a/src/views/dashboard/test/index.vue b/src/views/dashboard/test/index.vue new file mode 100644 index 0000000..920eb15 --- /dev/null +++ b/src/views/dashboard/test/index.vue @@ -0,0 +1,47 @@ + + + + + diff --git a/src/views/datamaintenance/components/datainfo.vue b/src/views/datamaintenance/components/datainfo.vue new file mode 100644 index 0000000..ecc0c57 --- /dev/null +++ b/src/views/datamaintenance/components/datainfo.vue @@ -0,0 +1,3 @@ + diff --git a/src/views/datamaintenance/components/datalist.vue b/src/views/datamaintenance/components/datalist.vue new file mode 100644 index 0000000..ecc0c57 --- /dev/null +++ b/src/views/datamaintenance/components/datalist.vue @@ -0,0 +1,3 @@ + diff --git a/src/views/datamaintenance/components/drawtool.vue b/src/views/datamaintenance/components/drawtool.vue new file mode 100644 index 0000000..ecc0c57 --- /dev/null +++ b/src/views/datamaintenance/components/drawtool.vue @@ -0,0 +1,3 @@ + diff --git a/src/views/datamaintenance/components/layerinfo.vue b/src/views/datamaintenance/components/layerinfo.vue new file mode 100644 index 0000000..ecc0c57 --- /dev/null +++ b/src/views/datamaintenance/components/layerinfo.vue @@ -0,0 +1,3 @@ + diff --git a/src/views/datamaintenance/components/layerlist.vue b/src/views/datamaintenance/components/layerlist.vue new file mode 100644 index 0000000..ecc0c57 --- /dev/null +++ b/src/views/datamaintenance/components/layerlist.vue @@ -0,0 +1,3 @@ + diff --git a/src/views/datamaintenance/components/map.vue b/src/views/datamaintenance/components/map.vue new file mode 100644 index 0000000..ecc0c57 --- /dev/null +++ b/src/views/datamaintenance/components/map.vue @@ -0,0 +1,3 @@ + diff --git a/src/views/datamaintenance/config/mapconfig.json b/src/views/datamaintenance/config/mapconfig.json new file mode 100644 index 0000000..32a035d --- /dev/null +++ b/src/views/datamaintenance/config/mapconfig.json @@ -0,0 +1,6 @@ +{ + "MAP_CENTER":[118.356494,35.117404], + "MAP_ZOOM":14, + "DARK_STYLE":"mapbox://styles/mapbox/navigation-guidance-night-v2", + "DAY_STYLE":"mapbox://styles/mapbox/light-v11" +} \ No newline at end of file diff --git a/src/views/datamaintenance/data/data.ts b/src/views/datamaintenance/data/data.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/views/datamaintenance/index.vue b/src/views/datamaintenance/index.vue new file mode 100644 index 0000000..cf785eb --- /dev/null +++ b/src/views/datamaintenance/index.vue @@ -0,0 +1,11 @@ + + diff --git a/src/views/datamaintenance/lib/findItem.ts b/src/views/datamaintenance/lib/findItem.ts new file mode 100644 index 0000000..8a970e6 --- /dev/null +++ b/src/views/datamaintenance/lib/findItem.ts @@ -0,0 +1,16 @@ +const { string } = require('vue-types'); + +const handleFindObjectArrayItem = ( + array: Array, + key: string, + val: string, +): Object | null => { + let obj: Object | null = null; + for (let i: number = 0; i < array.length; i++) { + if (array[i][key] == val) { + obj = array[i]; + break; + } + } + return obj; +}; diff --git a/src/views/datamaintenance/views/index.vue b/src/views/datamaintenance/views/index.vue new file mode 100644 index 0000000..ecc0c57 --- /dev/null +++ b/src/views/datamaintenance/views/index.vue @@ -0,0 +1,3 @@ + diff --git a/src/views/demo/Categories/Modal/index.vue b/src/views/demo/Categories/Modal/index.vue new file mode 100644 index 0000000..0f76560 --- /dev/null +++ b/src/views/demo/Categories/Modal/index.vue @@ -0,0 +1,111 @@ + + + + diff --git a/src/views/demo/Categories/index.vue b/src/views/demo/Categories/index.vue new file mode 100644 index 0000000..583f4dd --- /dev/null +++ b/src/views/demo/Categories/index.vue @@ -0,0 +1,362 @@ + + + + + + diff --git a/src/views/demo/Categories/util.ts b/src/views/demo/Categories/util.ts new file mode 100644 index 0000000..69f4ef1 --- /dev/null +++ b/src/views/demo/Categories/util.ts @@ -0,0 +1,101 @@ +export const columns = [ + { + title: '名称', + dataIndex: 'itemName', + resizable: true, + width: 100, + }, + { + title: '代码', + dataIndex: 'isDefault', + resizable: true, + width: 100, + }, + { + title: '值', + dataIndex: 'itemValue', + resizable: true, + width: 100, + }, + { + title: '是否可用', + dataIndex: 'enabledMark', + resizable: true, + width: 100, + }, + { + title: '排序号', + dataIndex: 'sortCode', + resizable: true, + width: 100, + }, + { + title: '描述', + dataIndex: 'description', + resizable: true, + width: 100, + }, + { + title: '分类标识', + dataIndex: 'itemCode', + resizable: true, + width: 100, + }, + { + title: '创建时间', + dataIndex: 'createDate', + resizable: true, + width: 100, + }, + { + title: '创建人', + dataIndex: 'createUserName', + resizable: true, + width: 100, + }, + { + title: '最后更新时间', + dataIndex: 'modifyDate', + resizable: true, + width: 100, + }, + { + title: '最后更新人', + dataIndex: 'modifyUserName', + resizable: true, + width: 100, + }, +]; +export const emptyLeftItem = { + itemCode: '', + itemName: '', +}; +export const emptyRightItem = { + id: '', + itemCode: '', + itemName: '', + itemValue: '', + enabledMark: '1', + sortCode: '', + description: '', + typeId: '', + prefix:'', +}; +export const dataProcess = (list) => { + return list.map((item) => { + return { + id: item.itemId, + title: item.itemName, + icon: 'home|svg', + key: item.itemCode, + }; + }); +}; +export const searchFormSchema = [ + { + field: 'key', + label: '关键字', + component: 'Input', + colProps: { span: 8 }, + }, +]; diff --git a/src/views/demo/ThematicSetting/UseModal/index.vue b/src/views/demo/ThematicSetting/UseModal/index.vue new file mode 100644 index 0000000..362146d --- /dev/null +++ b/src/views/demo/ThematicSetting/UseModal/index.vue @@ -0,0 +1,131 @@ + + + + + + diff --git a/src/views/demo/ThematicSetting/index.vue b/src/views/demo/ThematicSetting/index.vue new file mode 100644 index 0000000..aaeeddf --- /dev/null +++ b/src/views/demo/ThematicSetting/index.vue @@ -0,0 +1,108 @@ + + + + + + diff --git a/src/views/demo/ThematicSetting/util.ts b/src/views/demo/ThematicSetting/util.ts new file mode 100644 index 0000000..031e88b --- /dev/null +++ b/src/views/demo/ThematicSetting/util.ts @@ -0,0 +1,66 @@ +import { FormSchema } from '@/components/Table'; +export const searchFormSchema: FormSchema[] = [ + { + field: 'key', + label: '关键字', + component: 'Input', + colProps: { span: 8 }, + }, +]; +export const columns = [ + { + title: '专题名称', + dataIndex: 'topicName', + }, + { + title: '图斑类型', + dataIndex: 'caseTypes', + }, + { + title: '角色', + dataIndex: 'roles', + }, +]; +export const tableSetting = { + title: '专题列表', + columns, + showIndexColumn: false, + showTableSetting: true, + rowSelection: { + type: 'radio', + }, + useSearchForm: true, + formConfig: { + labelWidth: 120, + schemas: searchFormSchema, + }, + handleSearchInfoFn(info) { + return info; + }, + canResize: true, +}; +export const emptyTopicItem = { + topicName: '', + caseTypes: [], + roles: [], +}; +export const caseTypesColumns = [ + { + title: '图斑名称', + dataIndex: 'itemName', + }, + { + title: '状态', + dataIndex: 'enabledMark', + }, +]; +export const rolesColumns = [ + { + title: '角色名称', + dataIndex: 'name', + }, + { + title: '状态', + dataIndex: 'status', + }, +]; diff --git a/src/views/demo/charts/map/Baidu.vue b/src/views/demo/charts/map/Baidu.vue new file mode 100644 index 0000000..0420408 --- /dev/null +++ b/src/views/demo/charts/map/Baidu.vue @@ -0,0 +1,42 @@ + + diff --git a/src/views/demo/charts/mars3d/index.vue b/src/views/demo/charts/mars3d/index.vue new file mode 100644 index 0000000..6c23b5b --- /dev/null +++ b/src/views/demo/charts/mars3d/index.vue @@ -0,0 +1,154 @@ + + + + + + diff --git a/src/views/demo/charts/mars3d/map.js b/src/views/demo/charts/mars3d/map.js new file mode 100644 index 0000000..c5d72a6 --- /dev/null +++ b/src/views/demo/charts/mars3d/map.js @@ -0,0 +1,217 @@ +import * as mars3d from "mars3d" + +export let map // mars3d.Map三维地图对象 + +const creditHtml = `自然资源部 - 审图号:GS(2023)336号 + - 甲测资字1100471 - 服务条款 ` + +// 需要覆盖config.json中地图属性参数(当前示例框架中自动处理合并) +export const mapOptions = { + scene: { + center: { lat: 31.675177, lng: 117.323257, alt: 81193, heading: 359, pitch: -79 }, + highDynamicRange: false + }, + // 方式1:在创建地球前的参数中配置 + basemaps: [ + { + name: "天地图影像(EPSG:3857)", + icon: "img/basemaps/tdt_img.png", + type: "tdt", + layer: "img_d", + key: mars3d.Token.tiandituArr, + show: true, + credit: creditHtml + }, + { + name: "天地图电子(EPSG:3857)", + icon: "img/basemaps/tdt_vec.png", + type: "group", + layers: [ + { name: "底图", type: "tdt", layer: "vec_d", key: mars3d.Token.tiandituArr }, + { name: "注记", type: "tdt", layer: "vec_z", key: mars3d.Token.tiandituArr } + ], + credit: creditHtml + }, + { + name: "天地图地形(EPSG:3857)", + icon: "img/basemaps/tdt_ter.png", + type: "group", + layers: [ + { name: "底图", type: "tdt", layer: "ter_d", key: mars3d.Token.tiandituArr }, + { + name: "注记", + type: "tdt", + layer: "ter_z", + key: mars3d.Token.tiandituArr, + // 表示缩小和放大瓦片数据的过滤方式。默认值为LINEAR线性结构,大部分地图调整为最近方式过滤能够有效提升地图清晰度。 + minificationFilter: Cesium.TextureMinificationFilter.NEAREST, + magnificationFilter: Cesium.TextureMinificationFilter.NEAREST + } + ], + credit: creditHtml + }, + { + name: "天地图影像(EPSG:4326)", + icon: "img/basemaps/tdt_img.png", + type: "group", + layers: [ + { + name: "底图", + type: "tdt", + layer: "img_d", + crs: "EPSG:4326", + key: mars3d.Token.tiandituArr + }, + { + name: "注记", + type: "tdt", + layer: "img_z", + crs: "EPSG:4326", + key: mars3d.Token.tiandituArr + } + ], + credit: creditHtml + }, + { + name: "天地图电子(EPSG:4326)", + icon: "img/basemaps/tdt_vec.png", + type: "group", + layers: [ + { + name: "底图", + type: "tdt", + layer: "vec_d", + crs: "EPSG:4326", + key: mars3d.Token.tiandituArr + }, + { + name: "注记", + type: "tdt", + layer: "vec_z", + crs: "EPSG:4326", + key: mars3d.Token.tiandituArr + } + ], + credit: creditHtml + }, + { + name: "天地图地形(EPSG:4326)", + icon: "img/basemaps/tdt_ter.png", + type: "group", + layers: [ + { + name: "底图", + type: "tdt", + layer: "ter_d", + crs: "EPSG:4326", + key: mars3d.Token.tiandituArr + }, + { + name: "注记", + type: "tdt", + layer: "ter_z", + crs: "EPSG:4326", + key: mars3d.Token.tiandituArr + } + ], + credit: creditHtml + }, + + { + name: "天地图影像(英文)", + icon: "img/basemaps/tdt_img.png", + type: "group", + layers: [ + { name: "底图", type: "tdt", layer: "img_d", key: mars3d.Token.tiandituArr }, + { name: "底图", type: "tdt", layer: "img_e", key: mars3d.Token.tiandituArr } + ], + credit: creditHtml + }, + { + name: "天地图电子(英文)", + icon: "img/basemaps/tdt_vec.png", + type: "group", + layers: [ + { name: "底图", type: "tdt", layer: "vec_d", key: mars3d.Token.tiandituArr }, + { name: "底图", type: "tdt", layer: "vec_e", key: mars3d.Token.tiandituArr } + ], + credit: creditHtml + } + ] +} + +export const eventTarget = new mars3d.BaseClass() // 事件对象,用于抛出事件到面板中 + +/** + * 初始化地图业务,生命周期钩子函数(必须) + * 框架在地图初始化完成后自动调用该函数 + * @param {mars3d.Map} mapInstance 地图对象 + * @returns {void} 无 + */ +export function onMounted(mapInstance) { + map = mapInstance // 记录map + addCreditDOM() + + // 三维文字注记不清晰的原因:https://zhuanlan.zhihu.com/p/389945647 + + // 数值越高,性能越好,但视觉质量越差。默认值为2。 + // 针对不同的地图数据源,该值在 0.66~1.33 之间地图清晰度最高。 + map.scene.globe.maximumScreenSpaceError = 4 / 3 +} + +/** + * 释放当前地图业务的生命周期函数 + * @returns {void} 无 + */ +export function onUnmounted() { + removeCreditDOM() + map = null +} + +// 叠加的图层 +let tileLayer +export function addTileLayer() { + removeTileLayer() + + // 方式2:在创建地球后调用addLayer添加图层(直接new对应type类型的图层类) + tileLayer = new mars3d.layer.TdtLayer({ + name: "天地图影像注记", + layer: "img_z", + key: mars3d.Token.tiandituArr + }) + map.addLayer(tileLayer) +} + +export function removeTileLayer() { + if (tileLayer) { + map.removeLayer(tileLayer, true) + tileLayer = null + } +} + + + + +// 在下侧状态栏增加一个额外div展示图层版权信息 +let creditDOM +function addCreditDOM() { + const locationBar = map.controls.locationBar?.container + if (locationBar) { + creditDOM = mars3d.DomUtil.create("div", "mars3d-locationbar-content mars3d-locationbar-autohide", locationBar) + creditDOM.style["pointer-events"] = "all" + creditDOM.style.float = "left" + creditDOM.style.marginLeft = "20px" + + creditDOM.innerHTML = map.basemap?.options?.credit || "" + + map.on(mars3d.EventType.changeBasemap, function (event) { + creditDOM.innerHTML = event.layer?.options?.credit || "" + }) + } +} +function removeCreditDOM() { + if (creditDOM) { + mars3d.DomUtil.remove(creditDOM) + creditDOM = null + } +} diff --git a/src/views/demo/form-design/components/VFormCreate/components/FormRender.vue b/src/views/demo/form-design/components/VFormCreate/components/FormRender.vue new file mode 100644 index 0000000..14a45db --- /dev/null +++ b/src/views/demo/form-design/components/VFormCreate/components/FormRender.vue @@ -0,0 +1,278 @@ + + + + diff --git a/src/views/demo/form-design/components/VFormCreate/index.vue b/src/views/demo/form-design/components/VFormCreate/index.vue new file mode 100644 index 0000000..5b035a5 --- /dev/null +++ b/src/views/demo/form-design/components/VFormCreate/index.vue @@ -0,0 +1,156 @@ + + + + + diff --git a/src/views/demo/form-design/components/VFormDesign/components/CodeModal.vue b/src/views/demo/form-design/components/VFormDesign/components/CodeModal.vue new file mode 100644 index 0000000..a20aa0b --- /dev/null +++ b/src/views/demo/form-design/components/VFormDesign/components/CodeModal.vue @@ -0,0 +1,83 @@ + + + diff --git a/src/views/demo/form-design/components/VFormDesign/components/ComponentProps.vue b/src/views/demo/form-design/components/VFormDesign/components/ComponentProps.vue new file mode 100644 index 0000000..1ff3f5a --- /dev/null +++ b/src/views/demo/form-design/components/VFormDesign/components/ComponentProps.vue @@ -0,0 +1,592 @@ + + + + + diff --git a/src/views/demo/form-design/components/VFormDesign/components/FormItemColumnProps.vue b/src/views/demo/form-design/components/VFormDesign/components/FormItemColumnProps.vue new file mode 100644 index 0000000..6324dc1 --- /dev/null +++ b/src/views/demo/form-design/components/VFormDesign/components/FormItemColumnProps.vue @@ -0,0 +1,64 @@ + + + diff --git a/src/views/demo/form-design/components/VFormDesign/components/FormItemProps.vue b/src/views/demo/form-design/components/VFormDesign/components/FormItemProps.vue new file mode 100644 index 0000000..06477b5 --- /dev/null +++ b/src/views/demo/form-design/components/VFormDesign/components/FormItemProps.vue @@ -0,0 +1,230 @@ + + + diff --git a/src/views/demo/form-design/components/VFormDesign/components/FormNode.vue b/src/views/demo/form-design/components/VFormDesign/components/FormNode.vue new file mode 100644 index 0000000..7f30d18 --- /dev/null +++ b/src/views/demo/form-design/components/VFormDesign/components/FormNode.vue @@ -0,0 +1,58 @@ + + + + diff --git a/src/views/demo/form-design/components/VFormDesign/components/FormNodeOperate.vue b/src/views/demo/form-design/components/VFormDesign/components/FormNodeOperate.vue new file mode 100644 index 0000000..f9b31ce --- /dev/null +++ b/src/views/demo/form-design/components/VFormDesign/components/FormNodeOperate.vue @@ -0,0 +1,87 @@ + + + + diff --git a/src/views/demo/form-design/components/VFormDesign/components/FormOptions.vue b/src/views/demo/form-design/components/VFormDesign/components/FormOptions.vue new file mode 100644 index 0000000..05e5945 --- /dev/null +++ b/src/views/demo/form-design/components/VFormDesign/components/FormOptions.vue @@ -0,0 +1,466 @@ + + + + + diff --git a/src/views/demo/form-design/components/VFormDesign/components/FormProps.vue b/src/views/demo/form-design/components/VFormDesign/components/FormProps.vue new file mode 100644 index 0000000..b8c41a0 --- /dev/null +++ b/src/views/demo/form-design/components/VFormDesign/components/FormProps.vue @@ -0,0 +1,273 @@ + + + + + diff --git a/src/views/demo/form-design/components/VFormDesign/components/ImportJsonModal.vue b/src/views/demo/form-design/components/VFormDesign/components/ImportJsonModal.vue new file mode 100644 index 0000000..f75fc41 --- /dev/null +++ b/src/views/demo/form-design/components/VFormDesign/components/ImportJsonModal.vue @@ -0,0 +1,136 @@ + + + + + diff --git a/src/views/demo/form-design/components/VFormDesign/components/JsonModal.vue b/src/views/demo/form-design/components/VFormDesign/components/JsonModal.vue new file mode 100644 index 0000000..d380754 --- /dev/null +++ b/src/views/demo/form-design/components/VFormDesign/components/JsonModal.vue @@ -0,0 +1,65 @@ + + + diff --git a/src/views/demo/form-design/components/VFormDesign/components/LayoutItem.vue b/src/views/demo/form-design/components/VFormDesign/components/LayoutItem.vue new file mode 100644 index 0000000..aa11db5 --- /dev/null +++ b/src/views/demo/form-design/components/VFormDesign/components/LayoutItem.vue @@ -0,0 +1,221 @@ + + + + + + diff --git a/src/views/demo/form-design/components/VFormDesign/components/PreviewCode.vue b/src/views/demo/form-design/components/VFormDesign/components/PreviewCode.vue new file mode 100644 index 0000000..95f89a1 --- /dev/null +++ b/src/views/demo/form-design/components/VFormDesign/components/PreviewCode.vue @@ -0,0 +1,95 @@ + + + + + diff --git a/src/views/demo/form-design/components/VFormDesign/components/RuleProps.vue b/src/views/demo/form-design/components/VFormDesign/components/RuleProps.vue new file mode 100644 index 0000000..90a6a3a --- /dev/null +++ b/src/views/demo/form-design/components/VFormDesign/components/RuleProps.vue @@ -0,0 +1,293 @@ + + + + + diff --git a/src/views/demo/form-design/components/VFormDesign/config/componentPropsConfig.ts b/src/views/demo/form-design/components/VFormDesign/config/componentPropsConfig.ts new file mode 100644 index 0000000..619846c --- /dev/null +++ b/src/views/demo/form-design/components/VFormDesign/config/componentPropsConfig.ts @@ -0,0 +1,1318 @@ +import { IBaseFormAttrs } from './formItemPropsConfig'; + +interface IBaseComponentProps { + [key: string]: IBaseFormAttrs[]; +} + +type BaseFormAttrs = Omit; + +export const baseComponentControlAttrs: Omit[] = [ + { + // 没有disabled属性的控件不能作为form控件 + name: 'disabled', + label: '禁用', + }, + { + // 没有disabled属性的控件不能作为form控件 + name: 'autofocus', + label: '自动获取焦点', + includes: [ + 'Input', + 'Select', + 'InputTextArea', + 'InputNumber', + 'DatePicker', + 'RangePicker', + 'MonthPicker', + 'TimePicker', + 'Cascader', + 'TreeSelect', + 'Switch', + 'AutoComplete', + 'Slider', + ], + }, + { + name: 'allowClear', + label: '可清除', + includes: [ + 'Input', + 'Select', + 'InputTextArea', + 'InputNumber', + 'DatePicker', + 'RangePicker', + 'MonthPicker', + 'TimePicker', + 'Cascader', + 'TreeSelect', + 'AutoComplete', + ], + }, + { name: 'fullscreen', label: '全屏', includes: ['Calendar'] }, + { + name: 'showSearch', + label: '可搜索', + includes: ['Select', 'TreeSelect', 'Cascader', 'Transfer'], + }, + { + name: 'showTime', + label: '显示时间', + includes: ['DatePicker', 'RangePicker', 'MonthPicker'], + }, + { + name: 'range', + label: '双向滑动', + includes: [], + }, + { + name: 'allowHalf', + label: '允许半选', + includes: ['Rate'], + }, + { + name: 'multiple', + label: '多选', + includes: ['Select', 'TreeSelect', 'Upload'], + }, + { + name: 'directory', + label: '文件夹', + includes: ['Upload'], + }, + { + name: 'withCredentials', + label: '携带cookie', + includes: ['Upload'], + }, + { + name: 'bordered', + label: '是否有边框', + includes: ['Select', 'Input'], + }, + { + name: 'defaultActiveFirstOption', + label: '高亮第一个选项', + component: 'Checkbox', + includes: ['Select', 'AutoComplete'], + }, + { + name: 'dropdownMatchSelectWidth', + label: '下拉菜单和选择器同宽', + component: 'Checkbox', + includes: ['Select', 'TreeSelect', 'AutoComplete'], + }, +]; + +//共用属性 +export const baseComponentCommonAttrs: Omit[] = [ + { + name: 'dataTable', + label: '数据表', + component: 'Select', + componentProps: { + placeholder: '请输入', + allowClear: true, + options: [], + }, + }, + { + name: 'fieldName', + label: '字段名', + component: 'Select', + componentProps: { + placeholder: '请输入', + options: [], + }, + }, + { + name: 'size', + label: '尺寸', + component: 'RadioGroup', + componentProps: { + options: [ + { + label: '默认', + value: 'default', + }, + { + label: '大', + value: 'large', + }, + { + label: '小', + value: 'small', + }, + ], + }, + includes: ['InputNumber', 'Input', 'Cascader', 'Button'], + }, + { + name: 'placeholder', + label: '占位符', + component: 'Input', + componentProps: { + placeholder: '请输入占位符', + }, + includes: [ + 'AutoComplete', + 'InputTextArea', + 'InputNumber', + 'Input', + 'InputTextArea', + 'Select', + 'DatePicker', + 'MonthPicker', + 'TimePicker', + 'TreeSelect', + 'Cascader', + ], + }, + // { + // name: 'style', + // label: '样式', + // component: 'Input', + // componentProps: { + // placeholder: '请输入样式', + // }, + // }, + { + name: 'open', + label: '一直展开下拉菜单', + component: 'RadioGroup', + componentProps: { + options: [ + { + label: '默认', + value: undefined, + }, + { + label: '是', + value: true, + }, + { + label: '否', + value: false, + }, + ], + }, + includes: ['Select', 'AutoComplete'], + }, +]; + +// 设计子表属性 +export const designSubTableAttrs: Omit[] = [ + { + name: 'dataTable', + label: '数据表', + component: 'Select', + componentProps: { + placeholder: '请输入', + allowClear: true, + options: [], + }, + }, + { + name: 'fieldName', + label: '排序字段', + component: 'Select', + componentProps: { + placeholder: '请输入', + options: [], + }, + }, + + { + name: 'addBtnText', + label: '按钮文本', + component: 'Input', + componentProps: { + placeholder: '请输入', + options: [], + }, + }, +]; +// 设计子表控制属性 +export const designSubControlAttrs: Omit[] = [ + { + name: 'isDESC', + label: '是否倒叙', + }, + { + name: 'isAddBtn', + label: '添加按钮', + }, + { + name: 'isRemoveBtn', + label: '删除按钮', + }, + { + name: 'isShowNum', + label: '序列号', + }, + { + name: 'required', + label: '是否必填', + }, + { + name: 'multiterm', + label: '单行模式', + }, +]; + +const componentAttrs: IBaseComponentProps = { + AutoComplete: [ + { + name: 'backfill', + label: '自动回填', + component: 'Switch', + componentProps: { + span: 8, + }, + }, + { + name: 'defaultOpen', + label: '是否默认展开下拉菜单', + component: 'Checkbox', + }, + ], + IconPicker: [ + { + name: 'mode', + label: '模式', + component: 'RadioGroup', + componentProps: { + options: [ + { label: 'ICONIFY', value: null }, + { label: 'SVG', value: 'svg' }, + // { label: '组合', value: 'combobox' }, + ], + }, + }, + ], + + // https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/input#%3Cinput%3E_types + Input: [ + { + name: 'type', + label: '类型', + component: 'Select', + componentProps: { + options: [ + { value: 'text', label: '文本' }, + { value: 'search', label: '搜索' }, + { value: 'number', label: '数字' }, + { value: 'range', label: '数字范围' }, + { value: 'password', label: '密码' }, + { value: 'date', label: '日期' }, + { value: 'datetime-local', label: '日期-无时区' }, + { value: 'time', label: '时间' }, + { value: 'month', label: '年月' }, + { value: 'week', label: '星期' }, + { value: 'email', label: '邮箱' }, + { value: 'url', label: 'URL' }, + { value: 'tel', label: '电话号码' }, + { value: 'file', label: '文件' }, + { value: 'button', label: '按钮' }, + { value: 'submit', label: '提交按钮' }, + { value: 'reset', label: '重置按钮' }, + { value: 'radio', label: '单选按钮' }, + { value: 'checkbox', label: '复选框' }, + { value: 'color', label: '颜色' }, + { value: 'image', label: '图像' }, + { value: 'hidden', label: '隐藏' }, + ], + }, + }, + { + name: 'defaultValue', + label: '默认值', + component: 'Input', + componentProps: { + type: 'text', + placeholder: '请输入默认值', + }, + }, + { + name: 'prefix', + label: '前缀', + component: 'Input', + componentProps: { + type: 'text', + placeholder: '请输入前缀', + }, + }, + { + name: 'suffix', + label: '后缀', + component: 'Input', + componentProps: { + type: 'text', + placeholder: '请输入后缀', + }, + }, + { + name: 'addonBefore', + label: '前置标签', + component: 'Input', + componentProps: { + type: 'text', + placeholder: '请输入前置标签', + }, + }, + { + name: 'addonAfter', + label: '后置标签', + component: 'Input', + componentProps: { + type: 'text', + placeholder: '请输入后置标签', + }, + }, + { + name: 'maxLength', + label: '最大长度', + component: 'InputNumber', + componentProps: { + type: 'text', + placeholder: '请输入最大长度', + }, + }, + ], + + InputNumber: [ + { + name: 'defaultValue', + label: '默认值', + component: 'InputNumber', + componentProps: { + placeholder: '请输入默认值', + }, + }, + { + name: 'min', + label: '最小值', + component: 'InputNumber', + componentProps: { + type: 'text', + placeholder: '请输入最小值', + }, + }, + { + name: 'max', + label: '最大值', + component: 'InputNumber', + componentProps: { + type: 'text', + placeholder: '请输入最大值', + }, + }, + { + name: 'precision', + label: '数值精度', + component: 'InputNumber', + componentProps: { + type: 'text', + placeholder: '请输入最大值', + }, + }, + { + name: 'step', + label: '步长', + component: 'InputNumber', + componentProps: { + type: 'text', + placeholder: '请输入步长', + }, + }, + { + name: 'decimalSeparator', + label: '小数点', + component: 'Input', + componentProps: { type: 'text', placeholder: '请输入小数点' }, + }, + { + name: 'addonBefore', + label: '前置标签', + component: 'Input', + componentProps: { + type: 'text', + placeholder: '请输入前置标签', + }, + }, + { + name: 'addonAfter', + label: '后置标签', + component: 'Input', + componentProps: { + type: 'text', + placeholder: '请输入后置标签', + }, + }, + { + name: 'controls', + label: '是否显示增减按钮', + component: 'Checkbox', + }, + { + name: 'keyboard', + label: '是否启用键盘快捷行为', + component: 'Checkbox', + }, + { + name: 'stringMode', + label: '字符值模式', + component: 'Checkbox', + }, + { + name: 'bordered', + label: '是否有边框', + component: 'Checkbox', + }, + ], + InputTextArea: [ + { + name: 'defaultValue', + label: '默认值', + component: 'Input', + componentProps: { + type: 'text', + placeholder: '请输入默认值', + }, + }, + { + name: 'maxlength', + label: '最大长度', + component: 'InputNumber', + componentProps: { + placeholder: '请输入最大长度', + }, + }, + { + name: 'minlength', + label: '最小长度', + component: 'InputNumber', + componentProps: { + placeholder: '请输入最小长度', + }, + }, + { + name: 'cols', + label: '可见列数', + component: 'InputNumber', + componentProps: { + placeholder: '请输入可见列数', + min: 0, + }, + }, + { + name: 'rows', + label: '可见行数', + component: 'InputNumber', + componentProps: { + placeholder: '请输入可见行数', + min: 0, + }, + }, + { + name: 'minlength', + label: '最小长度', + component: 'InputNumber', + componentProps: { + placeholder: '请输入最小长度', + }, + }, + { + name: 'autosize', + label: '自适应内容高度', + component: 'Checkbox', + }, + { + name: 'showCount', + label: '是否展示字数', + component: 'Checkbox', + }, + { + name: 'readonly', + label: '是否只读', + component: 'Checkbox', + }, + { + name: 'spellcheck', + label: '读写检查', + component: 'Checkbox', + }, + { + name: 'autocomplete', + label: '是否自动完成', + component: 'RadioGroup', + componentProps: { + options: [ + { label: '正常', value: null }, + { label: '开', value: 'on' }, + { label: '关', value: 'off' }, + ], + }, + }, + { + name: 'autocorrect', + label: '是否自动纠错', + component: 'RadioGroup', + componentProps: { + options: [ + { label: '正常', value: null }, + { label: '开', value: 'on' }, + { label: '关', value: 'off' }, + ], + }, + }, + ], + Select: [ + { + name: 'mode', + label: '选择模式(默认单选)', + component: 'RadioGroup', + componentProps: { + options: [ + { label: '单选', value: null }, + { label: '多选', value: 'multiple' }, + { label: '标签', value: 'tags' }, + // { label: '组合', value: 'combobox' }, + ], + }, + }, + { + name: 'autoClearSearchValue', + label: '是否在选中项后清空搜索框', + component: 'Checkbox', + }, + { + name: 'labelInValue', + label: '选项的label包装到value中', + component: 'Checkbox', + }, + { + name: 'showArrow', + label: '显示下拉小箭头', + component: 'Checkbox', + }, + { + name: 'defaultOpen', + label: '默认展开下拉菜单', + component: 'Checkbox', + }, + ], + Checkbox: [ + { + name: 'indeterminate', + label: '设置indeterminate状态', + component: 'Checkbox', + }, + ], + CheckboxGroup: [], + RadioGroup: [ + { + name: 'defaultValue', + label: '默认值', + component: 'Input', + componentProps: { + placeholder: '请输入默认值', + }, + }, + { + name: 'buttonStyle', + label: 'RadioButton的风格样式', + component: 'RadioGroup', + componentProps: { + options: [ + { + label: 'outline', + value: 'outline', + }, + { + label: 'solid', + value: 'solid', + }, + ], + }, + }, + { + name: 'optionType', + label: 'options类型', + component: 'RadioGroup', + componentProps: { + options: [ + { + label: '默认', + value: 'default', + }, + { + label: '按钮', + value: 'button', + }, + ], + //根据其它选项的值更新自身控件配置值 + //compProp当前组件的属性, + //configProps,当且组件的所有配置选项 + //self,当前配置的componentProps属性 + //返回真值进行更新 + // _propsFunc: (compProp, configProps, self) => { + // console.log("i'm called"); + // console.log(compProp, configProps, self); + // if (compProp['buttonStyle'] && compProp['buttonStyle'] == 'outline') { + // if (!self['disabled']) { + // self['disabled'] = true; + // return 1; + // } + // } else { + // if (self['disabled']) { + // self['disabled'] = false; + // return 1; + // } + // } + + // // return prop.optionType == 'button'; + // }, + }, + }, + { + name: 'size', + label: '尺寸', + component: 'RadioGroup', + componentProps: { + options: [ + { + label: '默认', + value: 'default', + }, + { + label: '大', + value: 'large', + }, + { + label: '小', + value: 'small', + }, + ], + }, + }, + ], + TimePicker: [ + { + name: 'format', + label: '展示格式(format)', + component: 'Input', + componentProps: { + placeholder: 'HH:mm:ss', + }, + }, + { + name: 'valueFormat', + label: '绑定值格式(valueFormat)', + component: 'Input', + componentProps: { + placeholder: 'HH:mm:ss', + }, + }, + ], + DatePicker: [ + { + name: 'format', + label: '展示格式(format)', + component: 'Input', + componentProps: { + placeholder: 'YYYY-MM-DD', + }, + }, + { + name: 'valueFormat', + label: '绑定值格式(valueFormat)', + component: 'Input', + componentProps: { + placeholder: 'YYYY-MM-DD', + }, + }, + ], + MonthPicker: [ + { + name: 'format', + label: '展示格式(format)', + component: 'Input', + componentProps: { + placeholder: 'YYYY-MM', + }, + }, + { + name: 'valueFormat', + label: '绑定值格式(valueFormat)', + component: 'Input', + componentProps: { + placeholder: 'YYYY-MM', + }, + }, + ], + RangePicker: [ + { + name: 'placeholder', + label: '占位符', + children: [ + { + name: '', + label: '', + component: 'Input', + }, + { + name: '', + label: '', + component: 'Input', + }, + ], + }, + { + name: 'format', + label: '展示格式(format)', + component: 'Input', + componentProps: { + placeholder: 'YYYY-MM-DD HH:mm:ss', + }, + }, + { + name: 'valueFormat', + label: '绑定值格式(valueFormat)', + component: 'Input', + componentProps: { + placeholder: 'YYYY-MM-DD', + }, + }, + ], + Slider: [ + { + name: 'defaultValue', + label: '默认值', + component: 'InputNumber', + componentProps: { + placeholder: '请输入默认值', + }, + }, + { + name: 'min', + label: '最小值', + component: 'InputNumber', + componentProps: { + placeholder: '请输入最小值', + }, + }, + { + name: 'max', + label: '最大值', + component: 'InputNumber', + componentProps: { + placeholder: '请输入最大值', + }, + }, + { + name: 'step', + label: '步长', + component: 'InputNumber', + componentProps: { + placeholder: '请输入步长', + }, + }, + { + name: 'tooltipPlacement', + label: 'Tooltip 展示位置', + component: 'Select', + componentProps: { + options: [ + { value: 'top', label: '上' }, + { value: 'left', label: '左' }, + { value: 'right', label: '右' }, + { value: 'bottom', label: '下' }, + { value: 'topLeft', label: '上右' }, + { value: 'topRight', label: '上左' }, + { value: 'bottomLeft', label: '右下' }, + { value: 'bottomRight', label: '左下' }, + { value: 'leftTop', label: '左下' }, + { value: 'leftBottom', label: '左上' }, + { value: 'rightTop', label: '右下' }, + { value: 'rightBottom', label: '右上' }, + ], + }, + }, + { + name: 'tooltipVisible', + label: '始终显示Tooltip', + component: 'Checkbox', + }, + { + name: 'dots', + label: '只能拖拽到刻度上', + component: 'Checkbox', + }, + { + name: 'range', + label: '双滑块模式', + component: 'Checkbox', + }, + { + name: 'reverse', + label: '反向坐标轴', + component: 'Checkbox', + }, + { + name: 'vertical', + label: '垂直方向', + component: 'Checkbox', + }, + { + name: 'included', + label: '值为包含关系', + component: 'Checkbox', + }, + ], + Rate: [ + { + name: 'defaultValue', + label: '默认值', + component: 'InputNumber', + componentProps: { + placeholder: '请输入默认值', + }, + }, + { + name: 'character', + label: '自定义字符', + component: 'Input', + componentProps: { + placeholder: '请输入自定义字符', + }, + }, + { + name: 'count', + label: 'start 总数', + component: 'InputNumber', + componentProps: { + placeholder: '请输入自定义字符', + }, + }, + ], + Switch: [ + { + name: 'checkedChildren', + label: '选中时的内容', + component: 'Input', + componentProps: { + placeholder: '请输入选中时的内容', + }, + }, + { + name: 'checkedValue', + label: '选中时的值', + component: 'Input', + componentProps: { + placeholder: '请输入选中时的值', + }, + }, + { + name: 'unCheckedChildren', + label: '非选中时的内容', + component: 'Input', + componentProps: { + placeholder: '请输入非选中时的内容', + }, + }, + { + name: 'unCheckedValue', + label: '非选中时的值', + component: 'Input', + componentProps: { + placeholder: '请输入非选中时的值', + }, + }, + { + name: 'loading', + label: '加载中的开关', + component: 'Checkbox', + }, + { + name: 'size', + label: '尺寸', + component: 'RadioGroup', + componentProps: { + options: [ + { + label: '默认', + value: 'default', + }, + { + label: '小', + value: 'small', + }, + ], + }, + }, + ], + TreeSelect: [ + { + name: 'defaultValue', + label: '默认值', + component: 'Input', + componentProps: { + placeholder: '请输入默认值', + }, + }, + { + name: 'searchPlaceholder', + label: '搜索框默认文字', + component: 'Input', + componentProps: { + placeholder: '请输入搜索框默认文字', + }, + }, + { + name: 'treeNodeFilterProp', + label: '输入项过滤对应的 treeNode 属性', + component: 'Input', + componentProps: { + defaultValue: 'value', + }, + }, + { + name: 'treeNodeLabelProp', + label: '作为显示的 prop 设置', + component: 'Input', + componentProps: { + defaultValue: 'title', + }, + }, + { + name: 'popupClassName', + label: '下拉菜单的 className 属性', + component: 'Input', + componentProps: { + placeholder: '请输入下拉菜单的 className 属性', + }, + }, + + { + name: 'labelInValue', + label: '选项的label包装到value中', + component: 'Checkbox', + }, + { + name: 'treeIcon', + label: '展示TreeNode title前的图标', + component: 'Checkbox', + }, + { + name: 'treeCheckable', + label: '选项可勾选', + component: 'Checkbox', + }, + { + name: 'treeCheckStrictly', + label: '节点选择完全受控', + component: 'Checkbox', + }, + { + name: 'treeDefaultExpandAll', + label: '默认展开所有', + component: 'Checkbox', + }, + { + name: 'treeLine', + label: '是否展示线条样式', + component: 'Checkbox', + }, + { + name: 'maxTagCount', + label: '最多显示多少个 tag', + component: 'InputNumber', + componentProps: { + placeholder: '最多显示多少个 tag', + }, + }, + { + name: 'size', + label: '尺寸', + component: 'RadioGroup', + componentProps: { + options: [ + { + label: '默认', + value: 'default', + }, + { + label: '小', + value: 'small', + }, + ], + }, + }, + ], + Cascader: [ + { + name: 'expandTrigger', + label: '次级展开方式(默认click)', + component: 'RadioGroup', + componentProps: { + options: [ + { + label: 'click', + value: 'click', + }, + { + label: 'hover', + value: 'hover', + }, + ], + }, + }, + ], + Button: [ + { + name: 'type', + label: '类型', + component: 'RadioGroup', + componentProps: { + options: [ + { + label: 'default', + value: 'default', + }, + { + label: 'primary', + value: 'primary', + }, + { + label: 'dashed', + value: 'dashed', + }, + { + label: 'link', + value: 'link', + }, + { + label: 'text', + value: 'text', + }, + ], + }, + }, + { + name: 'shape', + label: '形状', + component: 'RadioGroup', + componentProps: { + options: [ + { + label: '朴素按钮', + value: 'default', + }, + { + label: '圆形按钮', + value: 'circle', + }, + { + label: '圆角按钮', + value: 'round', + }, + ], + }, + }, + { + name: 'handle', + label: '操作', + component: 'RadioGroup', + componentProps: { + options: [ + { + label: '提交', + value: 'submit', + }, + { + label: '重置', + value: 'reset', + }, + ], + }, + }, + ], + Upload: [ + { + name: 'action', + label: '上传地址', + component: 'Input', + }, + { + name: 'name', + label: '附件参数名(name)', + component: 'Input', + }, + ], + ImageUpload: [ + { + name: 'server', + label: '文件服务器地址', + component: 'Input', + }, + { + name: 'action', + label: '文件上传接口', + component: 'Input', + }, + { + name: 'name', + label: '附件参数名', + component: 'Input', + }, + { + name: 'azimuth', + label: '添加方位角信息', + component: 'RadioGroup', + componentProps: { + options: [ + { + label: '开启', + value: true, + }, + { + label: '关闭', + value: false, + } + ], + }, + }, + ], + VideoUpload: [ + { + name: 'server', + label: '文件服务器地址', + component: 'Input', + }, + { + name: 'action', + label: '文件上传接口', + component: 'Input', + }, + { + name: 'name', + label: '附件参数名', + component: 'Input', + }, + ], + FileUpload: [ + { + name: 'server', + label: '文件服务器地址', + component: 'Input', + }, + { + name: 'action', + label: '文件上传接口', + component: 'Input', + }, + { + name: 'name', + label: '附件参数名', + component: 'Input', + }, + ], + // ColorPicker: [ + // { + // name: 'defaultValue', + // label: '默认值', + // component: 'AColorPicker', + // }, + // ], + slot: [ + { + name: 'slotName', + label: '插槽名称', + component: 'Input', + }, + ], + Transfer: [ + // { + // name: 'operations', + // label: '操作文案集合,顺序从上至下', + // component: 'Input', + // componentProps: { + // type: 'text', + // // defaultValue: ['>', '<'], + // }, + // }, + // { + // name: 'titles', + // label: '标题集合,顺序从左至右', + // component: 'Input', + // componentProps: { + // type: 'text', + // // defaultValue: ['', ''], + // }, + // }, + { + name: 'oneWay', + label: '展示为单向样式', + component: 'Checkbox', + }, + { + name: 'pagination', + label: '使用分页样式', + component: 'Checkbox', + }, + { + name: 'showSelectAll', + label: '展示全选勾选框', + component: 'Checkbox', + }, + ], +}; + +function deleteProps(list: Omit[], key: string) { + list.forEach((element, index) => { + if (element.name == key) { + list.splice(index, 1); + } + }); +} + +componentAttrs['StrengthMeter'] = componentAttrs['Input']; +componentAttrs['StrengthMeter'].push({ + name: 'visibilityToggle', + label: '是否显示切换按钮', + component: 'Checkbox', +}); + +deleteProps(componentAttrs['StrengthMeter'], 'type'); +deleteProps(componentAttrs['StrengthMeter'], 'prefix'); +deleteProps(componentAttrs['StrengthMeter'], 'defaultValue'); +deleteProps(componentAttrs['StrengthMeter'], 'suffix'); +//组件属性 +// name 控件的属性 +export const baseComponentAttrs: IBaseComponentProps = componentAttrs; + +//在所有的选项中查找需要配置项 +const findCompoentProps = (props, name) => { + const idx = props.findIndex((value: BaseFormAttrs) => { + return value.name === name; + }); + if (props[idx] && props[idx].componentProps) { + return props[idx].componentProps; + } +}; + +// 根据其它选项的值更新自身控件配置值 +export const componentPropsFuncs = { + RadioGroup: (compProp, options: BaseFormAttrs[]) => { + const props = findCompoentProps(options, 'size'); + if (props) { + if (compProp['optionType'] && compProp['optionType'] != 'button') { + props['disabled'] = true; + compProp['size'] = null; + } else { + props['disabled'] = false; + } + } + }, +}; diff --git a/src/views/demo/form-design/components/VFormDesign/config/formItemPropsConfig.ts b/src/views/demo/form-design/components/VFormDesign/config/formItemPropsConfig.ts new file mode 100644 index 0000000..202af23 --- /dev/null +++ b/src/views/demo/form-design/components/VFormDesign/config/formItemPropsConfig.ts @@ -0,0 +1,365 @@ +import { IAnyObject } from '../../../typings/base-type'; +import { baseComponents, commonComponents } from '../../../core/formItemConfig'; +import { Input, Select, RadioGroup, Slider } from 'ant-design-vue'; +import { Component } from 'vue'; + +export const globalConfigState: { span: number } = { + span: 24, +}; +export interface IBaseFormAttrs { + name: string; // 字段名 + label: string; // 字段标签 + component?: string | Component; // 属性控件 + componentProps?: IAnyObject; // 传递给控件的属性 + exclude?: string[]; // 需要排除的控件 + includes?: string[]; // 符合条件的组件 + on?: IAnyObject; + children?: IBaseFormAttrs[]; + category?: 'control' | 'input'; +} + +export interface IBaseFormItemControlAttrs extends IBaseFormAttrs { + target?: 'props' | 'options'; // 绑定到对象下的某个目标key中 +} + +export const baseItemColumnProps: IBaseFormAttrs[] = [ + { + name: 'span', + label: '栅格数', + component: 'Slider', + on: { + change(value: number) { + globalConfigState.span = value; + }, + }, + componentProps: { + max: 24, + min: 0, + marks: { 12: '' }, + }, + }, + + { + name: 'offset', + label: '栅格左侧的间隔格数', + component: 'Slider', + componentProps: { + max: 24, + min: 0, + marks: { 12: '' }, + }, + }, + { + name: 'order', + label: '栅格顺序,flex 布局模式下有效', + component: 'Slider', + componentProps: { + max: 24, + min: 0, + marks: { 12: '' }, + }, + }, + { + name: 'pull', + label: '栅格向左移动格数', + component: 'Slider', + componentProps: { + max: 24, + min: 0, + marks: { 12: '' }, + }, + }, + { + name: 'push', + label: '栅格向右移动格数', + component: 'Slider', + componentProps: { + max: 24, + min: 0, + marks: { 12: '' }, + }, + }, + { + name: 'xs', + label: '<576px 响应式栅格', + component: 'Slider', + componentProps: { + max: 24, + min: 0, + marks: { 12: '' }, + }, + }, + { + name: 'sm', + label: '≥576px 响应式栅格', + component: 'Slider', + componentProps: { + max: 24, + min: 0, + marks: { 12: '' }, + }, + }, + { + name: 'md', + label: '≥768p 响应式栅格', + component: 'Slider', + + componentProps: { + max: 24, + min: 0, + marks: { 12: '' }, + }, + }, + { + name: 'lg', + label: '≥992px 响应式栅格', + component: 'Slider', + componentProps: { + max: 24, + min: 0, + marks: { 12: '' }, + }, + }, + { + name: 'xl', + label: '≥1200px 响应式栅格', + component: 'Slider', + componentProps: { + max: 24, + min: 0, + marks: { 12: '' }, + }, + }, + { + name: 'xxl', + label: '≥1600px 响应式栅格', + component: 'Slider', + componentProps: { + max: 24, + min: 0, + marks: { 12: '' }, + }, + }, + { + name: '≥2000px', + label: '≥1600px 响应式栅格', + component: 'Slider', + componentProps: { + max: 24, + min: 0, + marks: { 12: '' }, + }, + }, +]; + +// 控件属性面板的配置项 +export const advanceFormItemColProps: IBaseFormAttrs[] = [ + { + name: 'labelCol', + label: '标签col', + component: Slider, + componentProps: { + max: 24, + min: 0, + marks: { 12: '' }, + }, + exclude: ['Grid', 'Tabs'], + }, + { + name: 'wrapperCol', + label: '控件-span', + component: Slider, + componentProps: { + max: 24, + min: 0, + marks: { 12: '' }, + }, + exclude: ['Grid', 'Tabs'], + }, +]; +// 控件属性面板的配置项 +export const baseFormItemProps: IBaseFormAttrs[] = [ + { + // 动态的切换控件的类型 + name: 'component', + label: '控件-FormItem', + component: Select, + componentProps: { + options: commonComponents.concat(baseComponents).map((item) => ({ + value: item.component, + label: item.label, + key: item.component + '===' + item.label, + })), + }, + exclude: ['Grid', 'Tabs'], + }, + { + name: 'label', + label: '标签', + component: Input, + componentProps: { + type: 'Input', + placeholder: '请输入标签', + }, + exclude: ['Grid', 'Tabs'], + }, + { + name: 'field', + label: '字段标识', + component: Input, + componentProps: { + type: 'InputTextArea', + placeholder: '请输入字段标识', + }, + exclude: ['Grid', 'Tabs'], + }, + { + name: 'defaultValue', + label: '默认值', + component: Input, + componentProps: { + placeholder: '请输入默认值', + }, + exclude: ['Grid', 'Tabs'], + }, + { + name: 'helpMessage', + label: '提示信息', + component: Input, + componentProps: { + placeholder: '请输入提示信息', + }, + exclude: ['Grid', 'Tabs'], + }, +]; + +// 控件属性面板的配置项 +export const advanceFormItemProps: IBaseFormAttrs[] = [ + { + name: 'labelAlign', + label: '标签对齐', + component: RadioGroup, + componentProps: { + options: [ + { + label: '靠左', + value: 'left', + }, + { + label: '靠右', + value: 'right', + }, + ], + }, + exclude: ['Grid', 'Tabs'], + }, + + { + name: 'help', + label: '提示', + component: Input, + componentProps: { + placeholder: '请输入提示信息', + }, + exclude: ['Grid', 'Tabs'], + }, + { + name: 'extra', + label: '额外消息', + component: Input, + componentProps: { + type: 'InputTextArea', + placeholder: '请输入额外消息', + }, + exclude: ['Grid', 'Tabs'], + }, + { + name: 'validateTrigger', + label: '检验触发', + component: Input, + componentProps: { + type: 'InputTextArea', + placeholder: '请输入', + }, + exclude: ['Grid', 'Tabs'], + }, + { + name: 'validateStatus', + label: '校验状态', + component: RadioGroup, + componentProps: { + options: [ + { + label: '默认', + value: '', + }, + { + label: '成功', + value: 'success', + }, + { + label: '警告', + value: 'warning', + }, + { + label: '错误', + value: 'error', + }, + { + label: '校验中', + value: 'validating', + }, + ], + }, + exclude: ['Grid', 'Tabs'], + }, +]; + +export const baseFormItemControlAttrs: IBaseFormItemControlAttrs[] = [ + { + name: 'required', + label: '必填项', + component: 'Checkbox', + exclude: ['alert'], + }, + { + name: 'hidden', + label: '隐藏', + component: 'Checkbox', + exclude: ['alert'], + }, + { + name: 'hiddenLabel', + component: 'Checkbox', + exclude: ['Grid', 'Tabs'], + label: '隐藏标签', + }, + { + name: 'colon', + label: 'label后面显示冒号', + component: 'Checkbox', + componentProps: {}, + exclude: ['Grid', 'Tabs'], + }, + { + name: 'hasFeedback', + label: '输入反馈', + component: 'Checkbox', + componentProps: {}, + includes: ['Input'], + }, + { + name: 'autoLink', + label: '自动关联', + component: 'Checkbox', + componentProps: {}, + includes: ['Input'], + }, + { + name: 'validateFirst', + label: '检验证错误停止', + component: 'Checkbox', + componentProps: {}, + includes: ['Input'], + }, +]; diff --git a/src/views/demo/form-design/components/VFormDesign/config/formItemPropsScript.ts b/src/views/demo/form-design/components/VFormDesign/config/formItemPropsScript.ts new file mode 100644 index 0000000..7abaaa7 --- /dev/null +++ b/src/views/demo/form-design/components/VFormDesign/config/formItemPropsScript.ts @@ -0,0 +1,99 @@ +export const formItemPropsScript = `脚本参数说明 +// 获取表单是新增还是编辑 +let update = utils.isUpdate(); +// 组件变更数据 +let data = utils.data(); + +// 数据设置 +// 获取主表数据 +let mainValue = utils.getValue('组件的字段标识'); +// 设置主表数据 +setFieldsValue(utils.setValue('组件的字段标识', '设置的值')); + +// 获取子表数据 +let childValue = getChildValue('组件的字段标识'); +// 添加子表数据 +subTableList.value = addChildValue(data); +data格式为[{组件的字段标识1: "value1", {组件的字段标识2: "value2"}]或者{组件的字段标识1: "value1"} +// 修改子表数据 +subTableList.value = addChildValue('组件的字段标识', '旧value', '新value'); +// 删除子表数据 +subTableList.value = deleteChildValue('组件的字段标识', 'value'); + +// 组件设置 +// 设置组件为隐藏 +formColumns.value = utils.setHide('组件的字段标识', false); +// 取消组件隐藏 +formColumns.value = utils.setHide('组件的字段标识', true); +// 设置组件为禁用 +formColumns.value = utils.setDisabled('组件的字段标识', true); +// 取消组件禁用 +formColumns.value = utils.setDisabled('组件的字段标识', false); +// 设置组件为必填 +formColumns.value = utils.setRequired('组件的字段标识', true); +// 设置组件不为必填 +formColumns.value = utils.setRequired('组件的字段标识', false); + +// 功能设置 +// 提示消息 +utils.message('提示信息', '提示类型'); +提示类型:success(成功)、error(错误)、warn(警告)、info(默认) +// 获取登录者信息 +var loginUser = utils.loginUser(); +loginUser返回值为{ account: 账号, name: 姓名 } + +// 回调方法 +// get请求 +// 需要用到回调方法 +// 例子:let resGet = await utils.httpGet('/api/FormScheme/LoadFormPage', { page: 1, limit: 10 }); +let resGet = await utils.httpGet(url, params); +url:api地址, params:参数 + +// post请求 +let resPost = await utils.httpPost(url, params); +url:api地址, params:参数 + +// put请求 +// 需要用到回调方法 +let resPut = await utils.httpPut(url, params); +url:api地址, params:参数 +`; + + +export const options_json = `{ + "options": [ + { + "label": "选项1", + "value": "1", + "children": [ + { + "label": "选项3", + "value": "3" + } + ] + }, + { + "label": "选项2", + "value": "2" + } + ] +}`; + +export const treeData_json = `{ + "treeData": [ + { + "label": "选项1", + "value": "1", + "children": [ + { + "label": "选项3", + "value": "3" + } + ] + }, + { + "label": "选项2", + "value": "2" + } + ] +}`; \ No newline at end of file diff --git a/src/views/demo/form-design/components/VFormDesign/index.vue b/src/views/demo/form-design/components/VFormDesign/index.vue new file mode 100644 index 0000000..9f67aae --- /dev/null +++ b/src/views/demo/form-design/components/VFormDesign/index.vue @@ -0,0 +1,476 @@ + + + + + diff --git a/src/views/demo/form-design/components/VFormDesign/modules/CollapseItem.vue b/src/views/demo/form-design/components/VFormDesign/modules/CollapseItem.vue new file mode 100644 index 0000000..ce36311 --- /dev/null +++ b/src/views/demo/form-design/components/VFormDesign/modules/CollapseItem.vue @@ -0,0 +1,112 @@ + + + + diff --git a/src/views/demo/form-design/components/VFormDesign/modules/FormComponentPanel.vue b/src/views/demo/form-design/components/VFormDesign/modules/FormComponentPanel.vue new file mode 100644 index 0000000..cfcee61 --- /dev/null +++ b/src/views/demo/form-design/components/VFormDesign/modules/FormComponentPanel.vue @@ -0,0 +1,193 @@ + + + + + diff --git a/src/views/demo/form-design/components/VFormDesign/modules/PropsPanel.vue b/src/views/demo/form-design/components/VFormDesign/modules/PropsPanel.vue new file mode 100644 index 0000000..7c908bf --- /dev/null +++ b/src/views/demo/form-design/components/VFormDesign/modules/PropsPanel.vue @@ -0,0 +1,98 @@ + + + + + diff --git a/src/views/demo/form-design/components/VFormDesign/modules/Toolbar.vue b/src/views/demo/form-design/components/VFormDesign/modules/Toolbar.vue new file mode 100644 index 0000000..3abfd83 --- /dev/null +++ b/src/views/demo/form-design/components/VFormDesign/modules/Toolbar.vue @@ -0,0 +1,139 @@ + + + + + diff --git a/src/views/demo/form-design/components/VFormDesign/styles/drag.less b/src/views/demo/form-design/components/VFormDesign/styles/drag.less new file mode 100644 index 0000000..3d57c5c --- /dev/null +++ b/src/views/demo/form-design/components/VFormDesign/styles/drag.less @@ -0,0 +1,241 @@ +.draggable-box { + height: 100%; + overflow: auto; + background-color: @component-onlineform-formdesign-background-color; + + + :deep(.list-main) { + position: relative; + padding: 5px; + margin: 3px; + overflow: hidden; + border-radius: 4px; + + .moving { + position: relative; + box-sizing: border-box; + // 拖放移动中; + min-height: 35px; + padding: 0 !important; + overflow: hidden; + + &::before { + content: ''; + position: absolute; + top: 0; + right: 0; + width: 100%; + height: 3px; + background-color: @primary-color; + } + } + + .drag-move-box { + position: relative; + box-sizing: border-box; + min-height: 60px; + padding: 8px; + margin: 3px; + overflow: hidden; + transition: all 0.3s; + border-radius: 3px; + + &:hover { + background-color: @primary-hover-bg-color; + } + + // 选择时 start + &::before { + content: ''; + position: absolute; + top: 0; + right: -100%; + width: 0%; + height: 3px; + transition: all 0.3s; + outline: 3px solid @primary-color; + background-color: @primary-color; + } + + &.active { + outline: 3px solid @primary-color; + // outline-offset: 0; + background-color: @primary-hover-bg-color; + + &::before { + right: 0; + } + } + + // 选择时 end + .form-item-box { + position: relative; + box-sizing: border-box; + word-wrap: break-word; + + &::before { + content: ''; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + } + + .ant-form-item { + // 修改ant form-item的margin为padding + margin: 0; + padding-bottom: 6px; + } + } + + .show-key-box { + // 显示key + position: absolute; + right: 3px; + bottom: 2px; + // z-index: 999; + color: @primary-color; + font-size: 14px; + } + + .copy, + .delete { + position: absolute; + top: 0; + width: 30px; + height: 30px; + // z-index: 989; + transition: all 0.3s; + color: #fff; + line-height: 30px; + text-align: center; + + &.unactivated { + opacity: 0 !important; + pointer-events: none; + } + + &.active { + opacity: 1 !important; + } + } + + .copy { + right: 30px; + border-radius: 0 0 0 8px; + background-color: @primary-color; + } + + .delete { + right: 0; + background-color: @primary-color; + } + } + + .grid-box { + position: relative; + box-sizing: border-box; + width: 100%; + padding: 5px; + margin: 3px; + overflow: hidden; + transition: all 0.3s; + background-color: @layout-background-color; + border-radius: 3px; + + // 鼠标划过 + &:hover { + background-color: @layout-hover-bg-color; + } + + .form-item-box { + position: relative; + box-sizing: border-box; + + .ant-form-item { + // 修改ant form-item的margin为padding + margin: 0; + padding-bottom: 15px; + } + } + + .grid-row { + background-color: @layout-background-color; + + .grid-col { + .draggable-box { + min-width: 50px; + min-height: 80px; + border: 1px #ccc dashed; + // background: #fff; + + .list-main { + position: relative; + min-height: 83px; + border: 1px #ccc dashed; + } + } + } + } + + // 选择时 start + &::before { + content: ''; + position: absolute; + top: 0; + right: -100%; + width: 0%; + height: 3px; + transition: all 0.3s; + background: transparent; + } + + &.active { + outline: 3px solid @layout-color; + // outline-offset: 0; + background-color: @layout-hover-bg-color; + + &::before { + right: 0; + background-color: @layout-color; + } + } + // 选择时 end + > .copy-delete-box { + > .copy, + > .delete { + position: absolute; + top: 0; + width: 30px; + height: 30px; + // z-index: 989; + transition: all 0.3s; + color: #fff; + line-height: 30px; + text-align: center; + + &.unactivated { + opacity: 0 !important; + pointer-events: none; + } + + &.active { + opacity: 1 !important; + } + } + + > .copy { + right: 30px; + border-radius: 0 0 0 8px; + background-color: @layout-color; + } + + > .delete { + right: 0; + background-color: @layout-color; + } + } + } + } +} diff --git a/src/views/demo/form-design/components/VFormDesign/styles/variable.less b/src/views/demo/form-design/components/VFormDesign/styles/variable.less new file mode 100644 index 0000000..f40eb1e --- /dev/null +++ b/src/views/demo/form-design/components/VFormDesign/styles/variable.less @@ -0,0 +1,14 @@ +// 表单设计器样式 +@primary-color: #1E5EFFFF; +@layout-color: #A91EFFFF; + +@primary-hover-bg-color: #DFEAFC; +@layout-background-color: #E9E4F5; +@layout-hover-bg-color: #d7d2ff; + +@title-text-color: #fff; +@border-color: #ccc; + +@left-right-width: 280px; +@header-height: 56px; +@operating-area-height: 45px; diff --git a/src/views/demo/form-design/components/VFormItem/index.vue b/src/views/demo/form-design/components/VFormItem/index.vue new file mode 100644 index 0000000..31442bc --- /dev/null +++ b/src/views/demo/form-design/components/VFormItem/index.vue @@ -0,0 +1,328 @@ + + + + + diff --git a/src/views/demo/form-design/components/VFormItem/vFormItem.vue b/src/views/demo/form-design/components/VFormItem/vFormItem.vue new file mode 100644 index 0000000..c253bf9 --- /dev/null +++ b/src/views/demo/form-design/components/VFormItem/vFormItem.vue @@ -0,0 +1,68 @@ + + + + + + diff --git a/src/views/demo/form-design/components/VFormPreview/index.vue b/src/views/demo/form-design/components/VFormPreview/index.vue new file mode 100644 index 0000000..4e9fef5 --- /dev/null +++ b/src/views/demo/form-design/components/VFormPreview/index.vue @@ -0,0 +1,104 @@ + + + diff --git a/src/views/demo/form-design/components/VFormPreview/useForm.vue b/src/views/demo/form-design/components/VFormPreview/useForm.vue new file mode 100644 index 0000000..84db5a7 --- /dev/null +++ b/src/views/demo/form-design/components/VFormPreview/useForm.vue @@ -0,0 +1,71 @@ + + + diff --git a/src/views/demo/form-design/components/VformRender/index.vue b/src/views/demo/form-design/components/VformRender/index.vue new file mode 100644 index 0000000..178bf99 --- /dev/null +++ b/src/views/demo/form-design/components/VformRender/index.vue @@ -0,0 +1,112 @@ + + + diff --git a/src/views/demo/form-design/components/VformRender/useForm.vue b/src/views/demo/form-design/components/VformRender/useForm.vue new file mode 100644 index 0000000..84db5a7 --- /dev/null +++ b/src/views/demo/form-design/components/VformRender/useForm.vue @@ -0,0 +1,71 @@ + + + diff --git a/src/views/demo/form-design/components/index.ts b/src/views/demo/form-design/components/index.ts new file mode 100644 index 0000000..da7c2aa --- /dev/null +++ b/src/views/demo/form-design/components/index.ts @@ -0,0 +1,70 @@ +import type { Component } from 'vue'; +import { ComponentType } from '@/components/Form/src/types'; +import { IconPicker } from '@/components/Icon'; +/** + * Component list, register here to setting it in the form + */ +import { + Input, + Button, + Select, + Radio, + Checkbox, + AutoComplete, + Cascader, + DatePicker, + InputNumber, + Switch, + TimePicker, + // ColorPicker, + TreeSelect, + Slider, + Rate, + Divider, + Calendar, + Transfer, +} from 'ant-design-vue'; + +//ant-desing本身的Form控件库 + +const componentMap = new Map(); +componentMap.set('Radio', Radio); +componentMap.set('Button', Button); +componentMap.set('Calendar', Calendar); +componentMap.set('Input', Input); +componentMap.set('InputGuid', Input); +componentMap.set('InputGroup', Input.Group); +componentMap.set('InputPassword', Input.Password); +componentMap.set('InputSearch', Input.Search); +componentMap.set('InputTextArea', Input.TextArea); +componentMap.set('InputNumber', InputNumber); +componentMap.set('AutoComplete', AutoComplete); + +componentMap.set('Select', Select); +componentMap.set('TreeSelect', TreeSelect); +componentMap.set('Switch', Switch); +componentMap.set('RadioGroup', Radio.Group); +componentMap.set('Checkbox', Checkbox); +componentMap.set('CheckboxGroup', Checkbox.Group); +componentMap.set('Cascader', Cascader); +componentMap.set('Slider', Slider); +componentMap.set('Rate', Rate); +componentMap.set('Transfer', Transfer); +componentMap.set('DatePicker', DatePicker); +componentMap.set('MonthPicker', DatePicker.MonthPicker); +componentMap.set('RangePicker', DatePicker.RangePicker); +componentMap.set('WeekPicker', DatePicker.WeekPicker); +componentMap.set('TimePicker', TimePicker); + +componentMap.set('IconPicker', IconPicker); +componentMap.set('Divider', Divider); + +export function add(compName: ComponentType, component: Component) { + componentMap.set(compName, component); +} + +export function del(compName: ComponentType) { + componentMap.delete(compName); +} + +export { componentMap }; diff --git a/src/views/demo/form-design/core/formItemConfig.ts b/src/views/demo/form-design/core/formItemConfig.ts new file mode 100644 index 0000000..eaf5268 --- /dev/null +++ b/src/views/demo/form-design/core/formItemConfig.ts @@ -0,0 +1,689 @@ +/** + * @description:表单配置 + */ +import { IVFormComponent } from '../typings/v-form-component'; +import { isArray } from 'lodash-es'; +import { componentMap as VbenCmp, add } from '@/components/Form/src/componentMap'; +import { ComponentType } from '@/components/Form/src/types'; +import { uploadApi, fileUploadApi } from '@/api/sys/upload'; +import { componentMap as Cmp } from '../components'; +import { Component } from 'vue'; +import { getDeptList, getAccountList, getPosGroupList } from '@/api/demo/system'; + +//获取部门列表数据 +const deptTreeData = await Promise.all([getDeptListData()]); +function getDeptListData() { + let param = { + page: 1, + limit: 9999, + }; + return getDeptList(param).then((data) => { + return data; + }); +} +//获取职级列表数据 +const positionTreeData = await Promise.all([getPositionListData()]); +function getPositionListData() { + let param = { + page: 1, + limit: 9999, + }; + return getPosGroupList(param).then((data) => { + return data; + }); +} +//获取人员选择列表数据 +const userTreeData = await Promise.all([getUserListData()]); +function getUserListData() { + let param = { + page: 1, + limit: 9999, + }; + return getAccountList(param).then((data) => { + return data.items; + }); +} + +const componentMap = new Map(); + +//如果有其它控件,可以在这里初始化 + +//注册Ant控件库 +Cmp.forEach((value, key) => { + componentMap.set(key, value); + if (VbenCmp[key] == null) { + add(key as ComponentType, value); + } +}); +//注册vben控件库 +VbenCmp.forEach((value, key) => { + componentMap.set(key, value); +}); + +export { componentMap }; + +/** + * 设置自定义表单控件 + * @param {IVFormComponent | IVFormComponent[]} config + */ +export function setFormDesignComponents(config: IVFormComponent | IVFormComponent[]) { + if (isArray(config)) { + config.forEach((item) => { + const { componentInstance: component, ...rest } = item; + componentMap[item.component] = component; + customComponents.push(Object.assign({ props: {} }, rest)); + }); + } else { + const { componentInstance: component, ...rest } = config; + componentMap[config.component] = component; + customComponents.push(Object.assign({ props: {} }, rest)); + } +} + +//外部设置的自定义控件 +export const customComponents: IVFormComponent[] = [ + { + component: 'TreeSelect', + label: '职级选择', + icon: 'bi:list-stars', + field: '', + colProps: { span: 24 }, + componentProps: { + fieldNames: { + children: 'children', + label: 'name', + value: 'id', + }, + treeData: positionTreeData[0], + }, + }, + { + component: 'TreeSelect', + label: '部门选择', + icon: 'bi:people', + field: '', + colProps: { span: 24 }, + componentProps: { + fieldNames: { + children: 'children', + label: 'name', + value: 'id', + }, + treeData: deptTreeData[0], + }, + }, + { + component: 'Select', + label: '人员选择', + icon: 'bi:person', + field: '', + colProps: { span: 24 }, + componentProps: { + fieldNames: { + label: 'name', + value: 'account', + }, + options: userTreeData[0], + }, + }, + { + component: 'MapGeom', + label: '图斑', + icon: 'bi:box-arrow-in-up-left', + field: 'mapgeom', + colProps: { span: 24 }, + componentProps: {}, + }, +]; + +// 左侧控件列表与初始化的控件属性 +// props.slotName,会在formitem级别生成一个slot,并绑定当前record值 +// 属性props,类型为对象,不能为undefined或是null。 +export const commonComponents: IVFormComponent[] = [ + { + component: 'InputGuid', + label: 'GUID主键', + icon: 'bi:braces-asterisk', + field: '', + colProps: { span: 24 }, + componentProps: {}, + }, + { + component: 'Input', + label: '输入框', + icon: 'bi:braces', + field: '', + colProps: { span: 24 }, + componentProps: { + type: 'text', + }, + }, + { + component: 'InputNumber', + label: '数字输入框', + icon: 'ant-design:field-number-outlined', + field: '', + colProps: { span: 24 }, + componentProps: { style: 'width:200px' }, + }, + { + component: 'InputTextArea', + label: '文本域', + icon: 'ant-design:file-text-outlined', + field: '', + colProps: { span: 24 }, + componentProps: {}, + }, + { + component: 'Radio', + label: '单选框', + icon: 'carbon:radio-button-checked', + field: '', + colProps: { span: 24 }, + componentProps: {}, + }, + { + component: 'RadioGroup', + label: '单选框-组', + icon: 'bi:ui-radios-grid', + field: '', + colProps: { span: 24 }, + componentProps: { + options: [ + { + label: '选项1', + value: '1', + }, + { + label: '选项2', + value: '2', + }, + ], + }, + }, + { + component: 'Checkbox', + label: '复选框', + icon: 'bi:check-square', + colProps: { span: 24 }, + field: '', + componentProps: {}, + }, + { + component: 'CheckboxGroup', + label: '复选框-组', + icon: 'bi:ui-checks-grid', + field: '', + colProps: { span: 24 }, + componentProps: { + options: [ + { + label: '选项1', + value: '1', + }, + { + label: '选项2', + value: '2', + }, + ], + }, + }, + { + component: 'TimePicker', + label: '时间选择', + icon: 'healthicons:i-schedule-school-date-time', + field: '', + colProps: { span: 24 }, + componentProps: {}, + }, + { + component: 'DatePicker', + label: '日期选择', + icon: 'healthicons:i-schedule-school-date-time-outline', + field: '', + colProps: { span: 24 }, + componentProps: {}, + }, + { + component: 'MonthPicker', + label: '月份选择', + icon: 'healthicons:i-schedule-school-date-time-outline', + field: '', + colProps: { span: 24 }, + componentProps: { + placeholder: '请选择月份', + }, + }, + { + component: 'RangePicker', + label: '日期范围', + icon: 'healthicons:i-schedule-school-date-time-outline', + field: '', + colProps: { span: 24 }, + componentProps: { + placeholder: ['开始日期', '结束日期'], + }, + }, + { + component: 'Switch', + label: '开关', + icon: 'bi:toggle-off', + field: '', + colProps: { span: 24 }, + componentProps: {}, + }, + { + component: 'Button', + label: '按钮组件', + icon: 'ant-design:build-outlined', + field: '', + colProps: { span: 24 }, + hiddenLabel: true, + componentProps: { + type: 'default', + shape: 'default', + size: 'middle', + icon: '', + clickCode: '', + }, + }, + { + component: 'Select', + label: '下拉选择', + icon: 'gg:select', + field: '', + dataType:"1", + dataCode: '', + colProps: { span: 24 }, + componentProps: { + options: [ + { + label: '选项1', + value: '1', + }, + { + label: '选项2', + value: '2', + }, + ], + }, + }, + { + component: 'TreeSelect', + label: '树形选择', + icon: 'clarity:tree-view-line', + field: '', + colProps: { span: 24 }, + componentProps: { + treeData: [ + { + label: '选项1', + value: '1', + children: [ + { + label: '选项3', + value: '3', + }, + ], + }, + { + label: '选项2', + value: '2', + }, + ], + }, + }, + { + component: 'Cascader', + label: '级联选择', + icon: 'ant-design:block-outlined', + field: '', + colProps: { span: 24 }, + componentProps: { + options: [ + { + label: '选项1', + value: '1', + children: [ + { + label: '选项3', + value: '3', + }, + ], + }, + { + label: '选项2', + value: '2', + }, + ], + }, + }, + { + component: 'Transfer', + label: '穿梭框', + icon: 'bx:bx-transfer-alt', + field: '', + colProps: { span: 24 }, + componentProps: { + titles: ['', ''], + dataSource: [ + { + key: 'key-1', + title: '标题1', + description: '描述1', + disabled: false, + }, + { + key: 'key-2', + title: '标题2', + description: '描述2', + disabled: false, + }, + { + key: 'key-3', + title: '标题3', + description: '描述3', + disabled: false, + }, + ], + targetKeys: [], + // selectedKeys: [], + }, + }, +]; + +export const baseComponents: IVFormComponent[] = [ + { + component: 'InputCountDown', + label: '倒计时输入', + icon: 'ant-design:hourglass-outlined', + colProps: { span: 24 }, + field: '', + componentProps: {}, + }, + { + component: 'IconPicker', + label: '图标选择器', + icon: 'bi:grid', + colProps: { span: 24 }, + field: '', + componentProps: {}, + }, + { + component: 'StrengthMeter', + label: '密码强度', + icon: 'wpf:password1', + colProps: { span: 24 }, + field: '', + componentProps: {}, + }, + { + component: 'AutoComplete', + label: '自动完成', + icon: 'bi:check2-circle', + colProps: { span: 24 }, + field: '', + componentProps: { + placeholder: '请输入正则表达式', + options: [ + { + value: '/^(?:(?:\\+|00)86)?1[3-9]\\d{9}$/', + label: '手机号码', + }, + { + value: '/^((ht|f)tps?:\\/\\/)?[\\w-]+(\\.[\\w-]+)+:\\d{1,5}\\/?$/', + label: '网址带端口号', + }, + ], + }, + }, + { + component: 'Slider', + label: '滑动输入条', + icon: 'vaadin:slider', + field: '', + colProps: { span: 24 }, + componentProps: {}, + }, + { + component: 'Rate', + label: '评分', + icon: 'ic:outline-star-rate', + field: '', + colProps: { span: 24 }, + componentProps: {}, + }, + // { + // component: 'ColorPicker', + // label: '颜色选择器', + // icon: 'carbon:color-palette', + // field: '', + // colProps: { span: 24 }, + // componentProps: { + // defaultValue: '', + // value: '', + // }, + // }, + { + component: 'CreateUser', + type: 'createuser', + label: '创建人员', + icon: 'mdi:account-check', + colProps: { span: 24 }, + field: '', + componentProps: {}, + }, + { + component: 'ModifyUser', + type: 'modifyuser', + label: '修改人员', + icon: 'mdi:account-edit', + colProps: { span: 24 }, + field: '', + componentProps: {}, + }, + { + component: 'CreateTime', + type: 'createtime', + label: '创建时间', + icon: 'ic:outline-event-available', + colProps: { span: 24 }, + field: '', + componentProps: {}, + }, + { + component: 'ModifyTime', + type: 'modifytime', + label: '修改时间', + icon: 'ic:outline-event', + colProps: { span: 24 }, + field: '', + componentProps: {}, + }, + { + component: 'FileUpload', + label: '文件上传', + icon: 'ant-design:file-add-outlined', + field: '', + colProps: { span: 24 }, + componentProps: { + api: fileUploadApi, + maxNumber: 10, + maxSize: 2, + name: 'files', + action: '/api/Files/Upload', + server: '', + }, + }, + { + component: 'ImageUpload', + label: '图片上传', + icon: 'ant-design:file-image-outlined', + field: '', + colProps: { span: 24 }, + componentProps: { + azimuth:false, + api: fileUploadApi, + maxNumber: 10, + accept: ['png', 'jpeg', 'jpg'], + maxSize: 50, + name: 'files', + action: '/api/Files/Upload', + server: '', + }, + }, + { + component: 'VideoUpload', + label: '视频上传', + icon: 'ant-design:video-camera-outlined', + field: '', + colProps: { span: 24 }, + componentProps: { + api: fileUploadApi, + maxNumber: 10, + accept: ['mp4', 'mov', 'avi'], + maxSize: 100, + name: 'files', + action: '/api/Files/Upload', + server: '', + }, + }, + { + component: 'slot', + label: '插槽', + icon: 'bi:inboxes', + field: '', + colProps: { span: 24 }, + componentProps: { + slotName: 'slotName', + }, + }, + { + component: 'Location', + label: '获取位置', + icon: 'ant-design:environment-outlined', + field: '', + colProps: { span: 24 }, + componentProps: { + api: () => 1, + maxNumber: 10, + accept: ['mp4', 'mov', 'avi'], + maxSize: 100, + }, + }, + { + component: 'Divider', + label: '分割线', + icon: 'radix-icons:divider-horizontal', + colProps: { span: 24 }, + field: '', + componentProps: { + orientation: 'center', + dashed: true, + }, + }, +]; + +// // https://next.antdv.com/components/transfer-cn +// const transferControl = ; + +// baseComponents.push(transferControl); + +export const layoutComponents: IVFormComponent[] = [ + { + component: 'Tabs', + label: '选项卡', + icon: 'ant-design:database-outlined', + colProps: { span: 24 }, + field: 'Tabs', + componentProps: { + options: [ + { + label: '选项卡1', + value: '1', + children: [], + }, + { + label: '选项卡2', + value: '2', + children: [], + }, + ], + }, + }, + { + field: '', + component: 'Grid', + label: '设计子表', + icon: 'bi:list-ul', + type: 'subTable', + componentProps: {}, + columns: [ + { + span: 24, + children: [], + }, + ], + colProps: { span: 24 }, + options: { + gutter: 0, + }, + }, + { + field: '', + component: 'Card', + label: '卡片布局', + icon: 'bi:card-text', + componentProps: {}, + columns: [ + { + span: 24, + children: [], + }, + ], + colProps: { span: 24 }, + options: { + gutter: 0, + }, + }, + { + component: 'CardGroup', + label: '卡片组', + icon: 'bi:card-list', + colProps: { span: 24 }, + field: '', + componentProps: { + options: [ + { + label: '卡片1', + value: '1', + field: 'use_card_1', + children: [], + }, + { + label: '卡片2', + field: 'use_card_2', + value: '2', + children: [], + }, + ], + }, + }, + { + field: '', + component: 'Grid', + label: '栅格布局', + icon: 'bi:border-all', + componentProps: {}, + columns: [ + { + span: 24, + children: [], + }, + ], + colProps: { span: 24 }, + options: { + gutter: 0, + }, + }, +]; diff --git a/src/views/demo/form-design/core/iconConfig.ts b/src/views/demo/form-design/core/iconConfig.ts new file mode 100644 index 0000000..2588b4a --- /dev/null +++ b/src/views/demo/form-design/core/iconConfig.ts @@ -0,0 +1,739 @@ +const iconConfig = { + filled: [ + 'account-book', + 'alert', + 'alipay-circle', + 'alipay-square', + 'aliwangwang', + 'amazon-circle', + 'android', + 'amazon-square', + 'api', + 'appstore', + 'audio', + 'apple', + 'backward', + 'bank', + 'behance-circle', + 'bell', + 'behance-square', + 'book', + 'box-plot', + 'bug', + 'bulb', + 'calculator', + 'build', + 'calendar', + 'camera', + 'car', + 'caret-down', + 'caret-left', + 'caret-right', + 'carry-out', + 'caret-up', + 'check-circle', + 'check-square', + 'chrome', + 'ci-circle', + 'clock-circle', + 'close-circle', + 'cloud', + 'close-square', + 'code-sandbox-square', + 'code-sandbox-circle', + 'code', + 'codepen-circle', + 'compass', + 'codepen-square', + 'contacts', + 'container', + 'control', + 'copy', + 'copyright-circle', + 'credit-card', + 'crown', + 'customer-service', + 'dashboard', + 'delete', + 'diff', + 'dingtalk-circle', + 'database', + 'dingtalk-square', + 'dislike', + 'dollar-circle', + 'down-circle', + 'down-square', + 'dribbble-circle', + 'dribbble-square', + 'dropbox-circle', + 'dropbox-square', + 'environment', + 'edit', + 'exclamation-circle', + 'euro-circle', + 'experiment', + 'eye-invisible', + 'eye', + 'facebook', + 'fast-backward', + 'fast-forward', + 'file-add', + 'file-excel', + 'file-exclamation', + 'file-image', + 'file-markdown', + 'file-pdf', + 'file-ppt', + 'file-text', + 'file-unknown', + 'file-word', + 'file-zip', + 'file', + 'filter', + 'fire', + 'flag', + 'folder-add', + 'folder', + 'folder-open', + 'forward', + 'frown', + 'fund', + 'funnel-plot', + 'gift', + 'github', + 'gitlab', + 'golden', + 'google-circle', + 'google-plus-circle', + 'google-plus-square', + 'google-square', + 'hdd', + 'heart', + 'highlight', + 'home', + 'hourglass', + 'html5', + 'idcard', + 'ie-circle', + 'ie-square', + 'info-circle', + 'instagram', + 'insurance', + 'interaction', + 'interation', + 'layout', + 'left-circle', + 'left-square', + 'like', + 'linkedin', + 'lock', + 'mail', + 'medicine-box', + 'medium-circle', + 'medium-square', + 'meh', + 'message', + 'minus-circle', + 'minus-square', + 'mobile', + 'money-collect', + 'pause-circle', + 'pay-circle', + 'notification', + 'phone', + 'picture', + 'pie-chart', + 'play-circle', + 'play-square', + 'plus-circle', + 'plus-square', + 'pound-circle', + 'printer', + 'profile', + 'project', + 'pushpin', + 'property-safety', + 'qq-circle', + 'qq-square', + 'question-circle', + 'read', + 'reconciliation', + 'red-envelope', + 'reddit-circle', + 'reddit-square', + 'rest', + 'right-circle', + 'rocket', + 'right-square', + 'safety-certificate', + 'save', + 'schedule', + 'security-scan', + 'setting', + 'shop', + 'shopping', + 'sketch-circle', + 'sketch-square', + 'skin', + 'slack-circle', + 'skype', + 'slack-square', + 'sliders', + 'smile', + 'snippets', + 'sound', + 'star', + 'step-backward', + 'step-forward', + 'stop', + 'switcher', + 'tablet', + 'tag', + 'tags', + 'taobao-circle', + 'taobao-square', + 'tool', + 'thunderbolt', + 'trademark-circle', + 'twitter-circle', + 'trophy', + 'twitter-square', + 'unlock', + 'up-circle', + 'up-square', + 'usb', + 'video-camera', + 'wallet', + 'warning', + 'wechat', + 'weibo-circle', + 'windows', + 'yahoo', + 'weibo-square', + 'yuque', + 'youtube', + 'zhihu-circle', + 'zhihu-square', + ], + outlined: [ + 'account-book', + 'alert', + 'alipay-circle', + 'aliwangwang', + 'android', + 'api', + 'appstore', + 'audio', + 'apple', + 'backward', + 'bank', + 'bell', + 'behance-square', + 'book', + 'box-plot', + 'bug', + 'bulb', + 'calculator', + 'build', + 'calendar', + 'camera', + 'car', + 'caret-down', + 'caret-left', + 'caret-right', + 'carry-out', + 'caret-up', + 'check-circle', + 'check-square', + 'chrome', + 'clock-circle', + 'close-circle', + 'cloud', + 'close-square', + 'code', + 'codepen-circle', + 'compass', + 'contacts', + 'container', + 'control', + 'copy', + 'credit-card', + 'crown', + 'customer-service', + 'dashboard', + 'delete', + 'diff', + 'database', + 'dislike', + 'down-circle', + 'down-square', + 'dribbble-square', + 'environment', + 'edit', + 'exclamation-circle', + 'experiment', + 'eye-invisible', + 'eye', + 'facebook', + 'fast-backward', + 'fast-forward', + 'file-add', + 'file-excel', + 'file-exclamation', + 'file-image', + 'file-markdown', + 'file-pdf', + 'file-ppt', + 'file-text', + 'file-unknown', + 'file-word', + 'file-zip', + 'file', + 'filter', + 'fire', + 'flag', + 'folder-add', + 'folder', + 'folder-open', + 'forward', + 'frown', + 'fund', + 'funnel-plot', + 'gift', + 'github', + 'gitlab', + 'hdd', + 'heart', + 'highlight', + 'home', + 'hourglass', + 'html5', + 'idcard', + 'info-circle', + 'instagram', + 'insurance', + 'interaction', + 'interation', + 'layout', + 'left-circle', + 'left-square', + 'like', + 'linkedin', + 'lock', + 'mail', + 'medicine-box', + 'meh', + 'message', + 'minus-circle', + 'minus-square', + 'mobile', + 'money-collect', + 'pause-circle', + 'pay-circle', + 'notification', + 'phone', + 'picture', + 'pie-chart', + 'play-circle', + 'play-square', + 'plus-circle', + 'plus-square', + 'printer', + 'profile', + 'project', + 'pushpin', + 'property-safety', + 'question-circle', + 'read', + 'reconciliation', + 'red-envelope', + 'rest', + 'right-circle', + 'rocket', + 'right-square', + 'safety-certificate', + 'save', + 'schedule', + 'security-scan', + 'setting', + 'shop', + 'shopping', + 'skin', + 'skype', + 'slack-square', + 'sliders', + 'smile', + 'snippets', + 'sound', + 'star', + 'step-backward', + 'step-forward', + 'stop', + 'switcher', + 'tablet', + 'tag', + 'tags', + 'taobao-circle', + 'tool', + 'thunderbolt', + 'trophy', + 'unlock', + 'up-circle', + 'up-square', + 'usb', + 'video-camera', + 'wallet', + 'warning', + 'wechat', + 'weibo-circle', + 'windows', + 'yahoo', + 'weibo-square', + 'yuque', + 'youtube', + 'alibaba', + 'align-center', + 'align-left', + 'align-right', + 'alipay', + 'aliyun', + 'amazon', + 'ant-cloud', + 'apartment', + 'ant-design', + 'area-chart', + 'arrow-left', + 'arrow-down', + 'arrow-up', + 'arrows-alt', + 'arrow-right', + 'audit', + 'bar-chart', + 'barcode', + 'bars', + 'behance', + 'bg-colors', + 'block', + 'bold', + 'border-bottom', + 'border-left', + 'border-outer', + 'border-inner', + 'border-right', + 'border-horizontal', + 'border-top', + 'border-verticle', + 'border', + 'branches', + 'check', + 'ci', + 'close', + 'cloud-download', + 'cloud-server', + 'cloud-sync', + 'cloud-upload', + 'cluster', + 'codepen', + 'code-sandbox', + 'colum-height', + 'column-width', + 'column-height', + 'coffee', + 'copyright', + 'dash', + 'deployment-unit', + 'desktop', + 'dingding', + 'disconnect', + 'dollar', + 'double-left', + 'dot-chart', + 'double-right', + 'down', + 'drag', + 'download', + 'dribbble', + 'dropbox', + 'ellipsis', + 'enter', + 'euro', + 'exception', + 'exclamation', + 'export', + 'fall', + 'file-done', + 'file-jpg', + 'file-protect', + 'file-sync', + 'file-search', + 'font-colors', + 'font-size', + 'fork', + 'form', + 'fullscreen-exit', + 'fullscreen', + 'gateway', + 'global', + 'google-plus', + 'gold', + 'google', + 'heat-map', + 'history', + 'ie', + 'import', + 'inbox', + 'info', + 'italic', + 'key', + 'issues-close', + 'laptop', + 'left', + 'line-chart', + 'link', + 'line-height', + 'line', + 'loading-3-quarters', + 'loading', + 'login', + 'logout', + 'man', + 'medium', + 'medium-workmark', + 'menu-unfold', + 'menu-fold', + 'menu', + 'minus', + 'monitor', + 'more', + 'ordered-list', + 'number', + 'pause', + 'percentage', + 'paper-clip', + 'pic-center', + 'pic-left', + 'pic-right', + 'plus', + 'pound', + 'poweroff', + 'pull-request', + 'qq', + 'question', + 'radar-chart', + 'qrcode', + 'radius-bottomleft', + 'radius-bottomright', + 'radius-upleft', + 'radius-setting', + 'radius-upright', + 'reddit', + 'redo', + 'reload', + 'retweet', + 'right', + 'rise', + 'rollback', + 'safety', + 'robot', + 'scan', + 'search', + 'scissor', + 'select', + 'shake', + 'share-alt', + 'shopping-cart', + 'shrink', + 'sketch', + 'slack', + 'small-dash', + 'solution', + 'sort-descending', + 'sort-ascending', + 'stock', + 'swap-left', + 'swap-right', + 'strikethrough', + 'swap', + 'sync', + 'table', + 'team', + 'taobao', + 'to-top', + 'trademark', + 'transaction', + 'twitter', + 'underline', + 'undo', + 'unordered-list', + 'up', + 'upload', + 'user-add', + 'user-delete', + 'usergroup-add', + 'user', + 'usergroup-delete', + 'vertical-align-bottom', + 'vertical-align-middle', + 'vertical-align-top', + 'vertical-left', + 'vertical-right', + 'weibo', + 'wifi', + 'zhihu', + 'woman', + 'zoom-out', + 'zoom-in', + ], + twoTone: [ + 'account-book', + 'alert', + 'api', + 'appstore', + 'audio', + 'bank', + 'bell', + 'book', + 'box-plot', + 'bug', + 'bulb', + 'calculator', + 'build', + 'calendar', + 'camera', + 'car', + 'carry-out', + 'check-circle', + 'check-square', + 'clock-circle', + 'close-circle', + 'cloud', + 'close-square', + 'code', + 'compass', + 'contacts', + 'container', + 'control', + 'copy', + 'credit-card', + 'crown', + 'customer-service', + 'dashboard', + 'delete', + 'diff', + 'database', + 'dislike', + 'down-circle', + 'down-square', + 'environment', + 'edit', + 'exclamation-circle', + 'experiment', + 'eye-invisible', + 'eye', + 'file-add', + 'file-excel', + 'file-exclamation', + 'file-image', + 'file-markdown', + 'file-pdf', + 'file-ppt', + 'file-text', + 'file-unknown', + 'file-word', + 'file-zip', + 'file', + 'filter', + 'fire', + 'flag', + 'folder-add', + 'folder', + 'folder-open', + 'frown', + 'fund', + 'funnel-plot', + 'gift', + 'hdd', + 'heart', + 'highlight', + 'home', + 'hourglass', + 'html5', + 'idcard', + 'info-circle', + 'insurance', + 'interaction', + 'interation', + 'layout', + 'left-circle', + 'left-square', + 'like', + 'lock', + 'mail', + 'medicine-box', + 'meh', + 'message', + 'minus-circle', + 'minus-square', + 'mobile', + 'money-collect', + 'pause-circle', + 'notification', + 'phone', + 'picture', + 'pie-chart', + 'play-circle', + 'play-square', + 'plus-circle', + 'plus-square', + 'pound-circle', + 'printer', + 'profile', + 'project', + 'pushpin', + 'property-safety', + 'question-circle', + 'reconciliation', + 'red-envelope', + 'rest', + 'right-circle', + 'rocket', + 'right-square', + 'safety-certificate', + 'save', + 'schedule', + 'security-scan', + 'setting', + 'shop', + 'shopping', + 'skin', + 'sliders', + 'smile', + 'snippets', + 'sound', + 'star', + 'stop', + 'switcher', + 'tablet', + 'tag', + 'tags', + 'tool', + 'thunderbolt', + 'trademark-circle', + 'trophy', + 'unlock', + 'up-circle', + 'up-square', + 'usb', + 'video-camera', + 'wallet', + 'warning', + 'ci', + 'copyright', + 'dollar', + 'euro', + 'gold', + 'canlendar', + ], +}; + +export default iconConfig; diff --git a/src/views/demo/form-design/examples/baseForm.vue b/src/views/demo/form-design/examples/baseForm.vue new file mode 100644 index 0000000..e5ff6ac --- /dev/null +++ b/src/views/demo/form-design/examples/baseForm.vue @@ -0,0 +1,37 @@ + + diff --git a/src/views/demo/form-design/hooks/useFormDesignState.ts b/src/views/demo/form-design/hooks/useFormDesignState.ts new file mode 100644 index 0000000..865016e --- /dev/null +++ b/src/views/demo/form-design/hooks/useFormDesignState.ts @@ -0,0 +1,18 @@ +import { inject, Ref } from 'vue'; +import { IFormDesignMethods } from '../typings/form-type'; +import { IFormConfig } from '../typings/v-form-component'; + +/** + * 获取formDesign状态 + */ +export function useFormDesignState() { + const formConfig = inject('formConfig') as Ref; + const formDesignMethods = inject('formDesignMethods') as IFormDesignMethods; + return { formConfig, formDesignMethods }; +} + +export function useFormModelState() { + const formModel = inject('formModel') as Ref<{}>; + const setFormModel = inject('setFormModelMethod') as (key: String, value: any) => void; + return { formModel, setFormModel }; +} diff --git a/src/views/demo/form-design/hooks/useFormInstanceMethods.ts b/src/views/demo/form-design/hooks/useFormInstanceMethods.ts new file mode 100644 index 0000000..89db328 --- /dev/null +++ b/src/views/demo/form-design/hooks/useFormInstanceMethods.ts @@ -0,0 +1,60 @@ +import { IAnyObject } from '../typings/base-type'; +import { Ref, SetupContext, getCurrentInstance, toRaw, type EmitsOptions } from 'vue'; +import { cloneDeep, forOwn, isFunction } from 'lodash-es'; +import { AForm, IVFormComponent } from '../typings/v-form-component'; +import { Form } from 'ant-design-vue'; + +export function useFormInstanceMethods( + props: IAnyObject, + formdata, + context: SetupContext, + _formInstance: Ref, +) { + /** + * 绑定props和on中的上下文为parent + */ + const bindContext = () => { + const instance = getCurrentInstance(); + const vm = instance?.parent; + if (!vm) return; + + (props.formConfig.schemas as IVFormComponent[]).forEach((item) => { + // 绑定 props 中的上下文 + forOwn(item.componentProps, (value: any, key) => { + if (isFunction(value)) { + item.componentProps![key] = value.bind(vm); + } + }); + // 绑定事件监听(v-on)的上下文 + forOwn(item.on, (value: any, key) => { + if (isFunction(value)) { + item.componentProps![key] = value.bind(vm); + } + }); + }); + }; + bindContext(); + + const { emit } = context; + + const useForm = Form.useForm; + + const { resetFields, validate, clearValidate, validateField } = useForm(formdata, []); + + const submit = async () => { + //const _result = await validate(); + + const data = cloneDeep(toRaw(formdata.value)); + emit?.('submit', data); + props.formConfig.submit?.(data); + return data; + }; + + return { + validate, + validateField, + resetFields, + clearValidate, + submit, + }; +} diff --git a/src/views/demo/form-design/hooks/useVFormMethods.ts b/src/views/demo/form-design/hooks/useVFormMethods.ts new file mode 100644 index 0000000..191ae17 --- /dev/null +++ b/src/views/demo/form-design/hooks/useVFormMethods.ts @@ -0,0 +1,195 @@ +import { Ref, SetupContext, type EmitsOptions } from 'vue'; +import { IVFormComponent, IFormConfig, AForm } from '../typings/v-form-component'; +import { findFormItem, formItemsForEach } from '../utils'; +import { cloneDeep, isFunction } from 'lodash-es'; +import { IAnyObject } from '../typings/base-type'; + +interface IFormInstanceMethods extends AForm { + submit: () => Promise; +} + +export interface IProps { + formConfig: IFormConfig; + formModel: IAnyObject; +} + +type ISet = ( + field: string, + key: T, + value: IVFormComponent[T], +) => void; +// 获取当前field绑定的表单项 +type IGet = (field: string) => IVFormComponent | undefined; +// 获取field在formData中的值 +type IGetValue = (field: string) => any; +// 设置field在formData中的值并且触发校验 +type ISetValue = (field: string | IAnyObject, value?: any) => void; +// 隐藏field对应的表单项 +type IHidden = (field: string) => void; +// 显示field对应的表单项 +type IShow = (field: string) => void; +// 设置field对应的表单项绑定的props属性 +type ISetProps = (field: string, key: string, value: any) => void; +// 获取formData中的值 +type IGetData = () => Promise; +// 禁用表单,如果field为空,则禁用整个表单 +type IDisable = (field?: string | boolean) => void; +// 设置表单配置方法 +type ISetFormConfig = (key: string, value: any) => void; +interface ILinkOn { + [key: string]: Set; +} + +export interface IVFormMethods extends Partial { + set: ISet; + get: IGet; + getValue: IGetValue; + setValue: ISetValue; + hidden: IHidden; + show: IShow; + setProps: ISetProps; + linkOn: ILinkOn; + getData: IGetData; + disable: IDisable; +} +export function useVFormMethods( + props: IProps, + _context: SetupContext, + formInstance: Ref, + formInstanceMethods: Partial, +): IVFormMethods { + /** + * 根据field获取表单项 + * @param {string} field + * @return {IVFormComponent | undefined} + */ + const get: IGet = (field) => + findFormItem(props.formConfig.schemas, (item) => item.field === field); + + /** + * 根据表单field设置表单项字段值 + * @param {string} field + * @param {keyof IVFormComponent} key + * @param {never} value + */ + const set: ISet = (field, key, value) => { + const formItem = get(field); + if (formItem) formItem[key] = value; + }; + + /** + * 设置表单项的props + * @param {string} field 需要设置的表单项field + * @param {string} key 需要设置的key + * @param value 需要设置的值 + */ + const setProps: ISetProps = (field, key, value) => { + const formItem = get(field); + if (formItem?.componentProps) { + ['options', 'treeData'].includes(key) && setValue(field, undefined); + + formItem.componentProps[key] = value; + } + }; + /** + * 设置字段的值,设置后触发校验 + * @param {string} field 需要设置的字段 + * @param value 需要设置的值 + */ + const setValue: ISetValue = (field, value) => { + if (typeof field === 'string') { + // props.formData[field] = value + props.formModel[field] = value; + formInstance.value?.validateField(field, value, []); + } else { + const keys = Object.keys(field); + keys.forEach((key) => { + props.formModel[key] = field[key]; + formInstance.value?.validateField(key, field[key], []); + }); + } + }; + /** + * 设置表单配置方法 + * @param {string} key + * @param value + */ + const setFormConfig: ISetFormConfig = (key, value) => { + props.formConfig[key] = value; + }; + /** + * 根据表单项field获取字段值,如果field为空,则 + * @param {string} field 需要设置的字段 + */ + const getValue: IGetValue = (field) => { + const formData = cloneDeep(props.formModel); + return formData[field]; + }; + + /** + * 获取formData中的值 + * @return {Promise>} + */ + const getData: IGetData = async () => { + return cloneDeep(props.formModel); + }; + /** + * 隐藏指定表单项 + * @param {string} field 需要隐藏的表单项的field + */ + const hidden: IHidden = (field) => { + set(field, 'hidden', true); + }; + + /** + * 禁用表单 + * @param {string | undefined} field + */ + const disable: IDisable = (field) => { + typeof field === 'string' + ? setProps(field, 'disabled', true) + : setFormConfig('disabled', field !== false); + }; + + /** + * 显示表单项 + * @param {string} field 需要显示的表单项的field + */ + const show: IShow = (field) => { + set(field, 'hidden', false); + }; + + /** + * 监听表单字段联动时触发 + * @type {ILinkOn} + */ + const linkOn: ILinkOn = {}; + const initLink = (schemas: IVFormComponent[]) => { + // 首次遍历,查找需要关联字段的表单 + formItemsForEach(schemas, (formItem) => { + // 如果需要关联,则进行第二层遍历,查找表单中关联的字段,存到Set中 + formItemsForEach(schemas, (item) => { + if (!linkOn[item.field!]) linkOn[item.field!] = new Set(); + if (formItem.link?.includes(item.field!) && isFunction(formItem.update)) { + linkOn[item.field!].add(formItem); + } + }); + linkOn[formItem.field!].add(formItem); + }); + }; + initLink(props.formConfig.schemas); + + return { + linkOn, + setValue, + getValue, + hidden, + show, + set, + get, + setProps, + getData, + disable, + ...formInstanceMethods, + }; +} diff --git a/src/views/demo/form-design/index.vue b/src/views/demo/form-design/index.vue new file mode 100644 index 0000000..afa1370 --- /dev/null +++ b/src/views/demo/form-design/index.vue @@ -0,0 +1,42 @@ + + + + + diff --git a/src/views/demo/form-design/tests/import1.json b/src/views/demo/form-design/tests/import1.json new file mode 100644 index 0000000..1f3481d --- /dev/null +++ b/src/views/demo/form-design/tests/import1.json @@ -0,0 +1,54 @@ +{ + "schemas": [ + { + "field": "filename", + "component": "Input", + "label": "component.excel.fileName", + "rules": [ + { + "required": true + } + ] + }, + { + "field": "bookType", + "component": "Select", + "label": "component.excel.fileType", + "defaultValue": "xlsx", + "rules": [ + { + "required": true + } + ], + "componentProps": { + "options": [ + { + "label": "xlsx", + "value": "xlsx", + "key": "xlsx" + }, + { + "label": "html", + "value": "html", + "key": "html" + }, + { + "label": "csv", + "value": "csv", + "key": "csv" + }, + { + "label": "txt", + "value": "txt", + "key": "txt" + } + ] + } + } + ], + "layout": "horizontal", + "labelLayout": "flex", + "labelWidth": 100, + "labelCol": {}, + "wrapperCol": {} +} diff --git a/src/views/demo/form-design/typings/base-type.ts b/src/views/demo/form-design/typings/base-type.ts new file mode 100644 index 0000000..94f5d8c --- /dev/null +++ b/src/views/demo/form-design/typings/base-type.ts @@ -0,0 +1,10 @@ +export interface IAnyObject { + [key: string]: T; +} + +export interface IInputEvent { + target: { + value: any; + checked: boolean; + }; +} diff --git a/src/views/demo/form-design/typings/form-type.ts b/src/views/demo/form-design/typings/form-type.ts new file mode 100644 index 0000000..cf0219f --- /dev/null +++ b/src/views/demo/form-design/typings/form-type.ts @@ -0,0 +1,54 @@ +import { Ref } from 'vue'; +import { IAnyObject } from './base-type'; +import { IFormConfig, IVFormComponent } from './v-form-component'; + +export interface IToolbarMethods { + showModal: (jsonData: IAnyObject) => void; +} + +type ChangeTabKey = 1 | 2; +export interface IPropsPanel { + changeTab: (key: ChangeTabKey) => void; +} +export interface IState { + // 语言 + locale: any; + // 公用组件 + commonComponents: IVFormComponent[]; + // 公用组件 + baseComponents: IVFormComponent[]; + // 自定义组件 + customComponents: IVFormComponent[]; + // 布局组件 + layoutComponents: IVFormComponent[]; + // 属性面板实例 + propsPanel: Ref; + // json模态框实例 + jsonModal: Ref; + // 导入json数据模态框 + importJsonModal: Ref; + // 代码预览模态框 + codeModal: Ref; + // 预览模态框 + eFormPreview: Ref; + + eFormPreview2: Ref; +} + +export interface IFormDesignMethods { + // 设置当前选中的控件 + handleSetSelectItem(item: IVFormComponent): void; + // 添加控件到formConfig.formItems中 + handleListPush(item: IVFormComponent): void; + // 复制控件 + handleCopy(item?: IVFormComponent, isCopy?: boolean): void; + // 添加控件属性 + handleAddAttrs(schemas: IVFormComponent[], index: number): void; + setFormConfig(config: IFormConfig): void; + // 添加到表单中之前触发 + handleBeforeColAdd( + event: { newIndex: string }, + schemas: IVFormComponent[], + isCopy?: boolean, + ): void; +} diff --git a/src/views/demo/form-design/typings/v-form-component.ts b/src/views/demo/form-design/typings/v-form-component.ts new file mode 100644 index 0000000..dd27ce7 --- /dev/null +++ b/src/views/demo/form-design/typings/v-form-component.ts @@ -0,0 +1,398 @@ +import { IAnyObject } from './base-type'; +// import { ComponentOptions } from 'vue/types/options'; +import { ComponentOptions } from 'vue'; +import { IVFormMethods } from '../hooks/useVFormMethods'; +import { ColEx } from '@/components/Form/src/types'; + +import { SelectValue } from 'ant-design-vue/lib/select'; +import { validateOptions } from 'ant-design-vue/lib/form/useForm'; +import { RuleError } from 'ant-design-vue/lib/form/interface'; +import { FormItem } from '@/components/Form'; +import { FormLayout, FormProps } from 'ant-design-vue/lib/form/Form'; + +type labelLayout = 'flex' | 'Grid'; +export type PropsTabKey = 1 | 2 | 3; +type ColSpanType = number | string; + +declare type Value = [number, number] | number; + +/** + * 图层字段 + */ +export interface LayerFields { + // 图层数据表 + dataTable?: string; + // GID字段 + gidField?: string; + // 标注字段 + labelField?: string; + // geom字段 + geomField?: string; + // 标注字段options + labelFieldOptions?: any[]; +} +/** + * 图斑属性 + */ +export interface MapComponent { + width?: number; + minZoom?: number; + maxZoom?: number; + zoom?: number; + isShowMap?: boolean; + layers?: any[]; + baseLayers?: any[]; + mode?: string; + angle?: number; + center?: string; + chooseLayer?: string; + isAllowEditPolygon?: boolean; + isEnablePostionJump?: boolean; +} + +/** + * 组件属性 + */ +export interface IVFormComponent { + // extends Omit { + // 对应的字段 + field?: string; + // 组件类型 + component: string; + // 组件label + label?: string; + // 自定义组件控件实例 + componentInstance?: ComponentOptions; + // 组件icon + icon?: string; + // 组件校验规则 + rules?: Partial[]; + // 是否隐藏 + hidden?: boolean; + // 隐藏label + hiddenLabel?: boolean; + // 组件宽度 + width?: string; + // 是否必选 + required?: boolean; + // 必选提示 + message?: string; + // 提示信息 + helpMessage?: string; + // 传给给组件的属性,默认会吧所有的props都传递给控件 + componentProps?: IAnyObject; + // 监听组件事件对象,以v-on方式传递给控件 + on?: IAnyObject<(...any: []) => void>; + // 组件选项 + options?: IAnyObject; + // 唯一标识 + key?: string; + //默认值 + defaultValue?: string; + // Reference formModelItem + itemProps?: Partial; + + colProps?: Partial; + // 联动字段 + link?: string[]; + // 联动属性变化的回调 + update?: (value: any, formItem: IVFormComponent, fApi: IVFormMethods) => void; + // 控件栅格数 + // span?: number; + // 标签布局 + labelCol?: IAnyObject; + // 组件布局 + wrapperCol?: IAnyObject; + // 子控件 + columns?: Array<{ span: number; children: any[] }>; + // 图斑数据 + mapSetData?: MapComponent; + // 判断子表的字段 + type?: string; + // 下拉选择中字段选择类型 + dataType?: string; + // 下拉选择中选择的字典类型 + dataCode? : string; +} + +declare type namesType = string | string[]; + +/** + * 表单配置 + */ +export type PickAntFormConfig = Pick< + FormProps, + | 'layout' + | 'size' + | 'colon' + | 'labelAlign' + | 'disabled' + | 'labelCol' + | 'wrapperCol' + | 'hideRequiredMark' +>; + +// 使用extends 而不使用 &联结 是为了避免 type:check指令类型重载错误 +export interface IFormConfig extends PickAntFormConfig { + labelLayout?: labelLayout; + labelWidth?: number; + schemas: IVFormComponent[]; + currentItem?: IVFormComponent; + activeKey?: PropsTabKey; + status?: string; + defaultValue?: string; + beforeSetData?: string; + afterValidateForm?: string; + afterSaveEvent?: string; + changeDataEvent?: string; +} + +export interface AForm { + /** + * Hide required mark of all form items + * @default false + * @type boolean + */ + hideRequiredMark: boolean; + + /** + * The layout of label. You can set span offset to something like {span: 3, offset: 12} or sm: {span: 3, offset: 12} same as with + * @type IACol + */ + labelCol: IACol; + + /** + * Define form layout + * @default 'horizontal' + * @type string + */ + layout: FormLayout; + + /** + * The layout for input controls, same as labelCol + * @type IACol + */ + wrapperCol: IACol; + + /** + * change default props colon value of Form.Item (only effective when prop layout is horizontal) + * @type boolean + * @default true + */ + colon: boolean; + + /** + * text align of label of all items + * @type 'left' | 'right' + * @default 'left' + */ + labelAlign: 'left' | 'right'; + + /** + * data of form component + * @type object + */ + model: IAnyObject; + + /** + * validation rules of form + * @type object + */ + rules: IAnyObject; + + /** + * Default validate message. And its format is similar with newMessages's returned value + * @type any + */ + validateMessages?: any; + + /** + * whether to trigger validation when the rules prop is changed + * @type Boolean + * @default true + */ + validateOnRuleChange: boolean; + + /** + * validate the whole form. Takes a callback as a param. After validation, + * the callback will be executed with two params: a boolean indicating if the validation has passed, + * and an object containing all fields that fail the validation. Returns a promise if callback is omitted + * @type Function + */ + validate: (names?: namesType, option?: validateOptions) => Promise; + + /** + * validate one or several form items + * @type Function + */ + validateField: ( + name: string, + value: any, + rules: Record[], + option?: validateOptions, + ) => Promise; + /** + * reset all the fields and remove validation result + */ + resetFields: () => void; + + /** + * clear validation message for certain fields. + * The parameter is prop name or an array of prop names of the form items whose validation messages will be removed. + * When omitted, all fields' validation messages will be cleared + * @type string[] | string + */ + clearValidate: (props: string[] | string) => void; +} + +interface IACol { + /** + * raster number of cells to occupy, 0 corresponds to display: none + * @default none (0) + * @type ColSpanType + */ + span: Value; + + /** + * raster order, used in flex layout mode + * @default 0 + * @type ColSpanType + */ + order: ColSpanType; + + /** + * the layout fill of flex + * @default none + * @type ColSpanType + */ + flex: ColSpanType; + + /** + * the number of cells to offset Col from the left + * @default 0 + * @type ColSpanType + */ + offset: ColSpanType; + + /** + * the number of cells that raster is moved to the right + * @default 0 + * @type ColSpanType + */ + push: ColSpanType; + + /** + * the number of cells that raster is moved to the left + * @default 0 + * @type ColSpanType + */ + pull: ColSpanType; + + /** + * <576px and also default setting, could be a span value or an object containing above props + * @type { span: ColSpanType, offset: ColSpanType } | ColSpanType + */ + xs: { span: ColSpanType; offset: ColSpanType } | ColSpanType; + + /** + * ≥576px, could be a span value or an object containing above props + * @type { span: ColSpanType, offset: ColSpanType } | ColSpanType + */ + sm: { span: ColSpanType; offset: ColSpanType } | ColSpanType; + + /** + * ≥768px, could be a span value or an object containing above props + * @type { span: ColSpanType, offset: ColSpanType } | ColSpanType + */ + md: { span: ColSpanType; offset: ColSpanType } | ColSpanType; + + /** + * ≥992px, could be a span value or an object containing above props + * @type { span: ColSpanType, offset: ColSpanType } | ColSpanType + */ + lg: { span: ColSpanType; offset: ColSpanType } | ColSpanType; + + /** + * ≥1200px, could be a span value or an object containing above props + * @type { span: ColSpanType, offset: ColSpanType } | ColSpanType + */ + xl: { span: ColSpanType; offset: ColSpanType } | ColSpanType; + + /** + * ≥1600px, could be a span value or an object containing above props + * @type { span: ColSpanType, offset: ColSpanType } | ColSpanType + */ + xxl: { span: ColSpanType; offset: ColSpanType } | ColSpanType; +} + +export interface IValidationRule { + trigger?: 'change' | 'blur' | ['change', 'blur']; + /** + * validation error message + * @type string | Function + */ + message?: string | number; + + /** + * built-in validation type, available options: https://github.com/yiminghe/async-validator#type + * @default 'string' + * @type string + */ + type?: string; + + /** + * indicates whether field is required + * @default false + * @type boolean + */ + required?: boolean; + + /** + * treat required fields that only contain whitespace as errors + * @default false + * @type boolean + */ + whitespace?: boolean; + + /** + * validate the exact length of a field + * @type number + */ + len?: number; + + /** + * validate the min length of a field + * @type number + */ + min?: number; + + /** + * validate the max length of a field + * @type number + */ + max?: number; + + /** + * validate the value from a list of possible values + * @type string | string[] + */ + enum?: string | string[]; + + /** + * validate from a regular expression + * @type boolean + */ + pattern?: SelectValue; + + /** + * transform a value before validation + * @type Function + */ + transform?: (value: any) => any; + + /** + * custom validate function (Note: callback must be called) + * @type Function + */ + validator?: (rule: any, value: any, callback: () => void) => any; +} diff --git a/src/views/demo/form-design/utils/index.ts b/src/views/demo/form-design/utils/index.ts new file mode 100644 index 0000000..c9c1bd3 --- /dev/null +++ b/src/views/demo/form-design/utils/index.ts @@ -0,0 +1,203 @@ +// import { VueConstructor } from 'vue'; +import { IVFormComponent, IFormConfig, IValidationRule } from '../typings/v-form-component'; +import { cloneDeep, isArray, isFunction, isNumber, uniqueId } from 'lodash-es'; +import { v4 as uuidv4 } from 'uuid'; +// import { del } from '@vue/composition-api'; +// import { withInstall } from '@/utils'; + +/** + * 组件install方法 + * @param comp 需要挂载install方法的组件 + */ +// export function withInstall(comp: T) { +// return Object.assign(comp, { +// install(Vue: VueConstructor) { +// Vue.component(comp.name, comp); +// }, +// }); +// } + +/** + * 生成key + * @param [formItem] 需要生成 key 的控件,可选,如果不传,默认返回一个唯一 key + * @returns {string|boolean} 返回一个唯一 id 或者 false + */ +export function generateKey(formItem?: IVFormComponent): string | boolean { + if (formItem && formItem.component) { + const key = `${toLine(formItem.component)}_${uuidv4().replace(/-/g, '')}`; + formItem.key = key; + formItem.field = formItem.field || key; + + return true; + } + return `key_${uuidv4().replace(/-/g, '')}`; +} + +/** + * 移除数组中指定元素,value可以是一个数字下标,也可以是一个函数,删除函数第一个返回true的元素 + * @param array {Array} 需要移除元素的数组 + * @param value {number | ((item: T, index: number, array: Array) => boolean} + * @returns {T} 返回删除的数组项 + */ +export function remove( + array: Array, + value: number | ((item: T, index: number, array: Array) => boolean), +): T | undefined { + let removeVal: Array = []; + if (!isArray(array)) return undefined; + if (isNumber(value)) { + removeVal = array.splice(value, 1); + } else { + const index = array.findIndex(value); + if (index !== -1) { + removeVal = array.splice(index, 1); + } + } + return removeVal.shift(); +} + +/** + * 判断数据类型 + * @param value + */ +export function getType(value: any): string { + return Object.prototype.toString.call(value).slice(8, -1); +} + +/** + * 生成唯一guid + * @returns {String} 唯一id标识符 + */ +export function randomUUID(): string { + function S4() { + return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1); + } + return `${S4() + S4()}-${S4()}-${S4()}-${S4()}-${S4() + S4() + S4()}`; +} + +/** + * 驼峰转下划线 + * @param str + */ +export function toLine(str: string) { + return str.replace(/([A-Z])/g, '_$1').toLowerCase(); +} + +/** + * 遍历表单项 + * @param array + * @param cb + */ +export function formItemsForEach(array: IVFormComponent[], cb: (item: IVFormComponent) => void) { + if (!isArray(array)) return; + const traverse = (schemas: IVFormComponent[]) => { + if (schemas) { + schemas.forEach((formItem: IVFormComponent) => { + if (['Grid'].includes(formItem.component)) { + // 栅格布局 + formItem.columns?.forEach((item) => traverse(item.children)); + } else { + cb(formItem); + } + }); + } + }; + traverse(array); +} + +/** + * 查找表单项 + */ +export const findFormItem: ( + schemas: IVFormComponent[], + cb: (formItem: IVFormComponent) => boolean, +) => IVFormComponent | undefined = (schemas, cb) => { + let res; + const traverse = (schemas: IVFormComponent[]): boolean => { + return schemas.some((formItem: IVFormComponent) => { + const { component: type } = formItem; + // 处理栅格 + if (['Grid'].includes(type)) { + return formItem.columns?.some((item) => traverse(item.children)); + } + if (cb(formItem)) res = formItem; + return cb(formItem); + }); + }; + traverse(schemas); + return res; +}; + +/** + * 打开json模态框时删除当前项属性 + * @param formConfig {IFormConfig} + * @returns {IFormConfig} + */ +export const removeAttrs = (formConfig: IFormConfig): IFormConfig => { + const copyFormConfig = cloneDeep(formConfig); + delete copyFormConfig.currentItem; + delete copyFormConfig.activeKey; + copyFormConfig.schemas && + formItemsForEach(copyFormConfig.schemas, (item) => { + delete item.icon; + delete item.key; + }); + return copyFormConfig; +}; + +/** + * 处理异步选项属性,如 select treeSelect 等选项属性如果传递为函数并且返回Promise对象,获取异步返回的选项属性 + * @param {(() => Promise) | any[]} options + * @return {Promise} + */ +export const handleAsyncOptions = async ( + options: (() => Promise) | any[], +): Promise => { + try { + if (isFunction(options)) return await options(); + return options; + } catch { + return []; + } +}; + +/** + * 格式化表单项校验规则配置 + * @param {IVFormComponent[]} schemas + */ +export const formatRules = (schemas: IVFormComponent[]) => { + formItemsForEach(schemas, (item) => { + if ('required' in item) { + !isArray(item.rules) && (item.rules = []); + item.rules.push({ required: true, message: item.message }); + delete item['required']; + delete item['message']; + } + }); +}; + +/** + * 将校验规则中的正则字符串转换为正则对象 + * @param {IValidationRule[]} rules + * @return {IValidationRule[]} + */ +export const strToReg = (rules: IValidationRule[]) => { + const newRules = cloneDeep(rules); + return newRules.map((item) => { + if (item.pattern) item.pattern = runCode(item.pattern); + return item; + }); +}; + +/** + * 执行一段字符串代码,并返回执行结果,如果执行出错,则返回该参数 + * @param code + * @return {any} + */ +export const runCode = (code: any): T => { + try { + return new Function(`return ${code}`)(); + } catch { + return code; + } +}; diff --git a/src/views/demo/form-design/utils/message.ts b/src/views/demo/form-design/utils/message.ts new file mode 100644 index 0000000..1f3d71a --- /dev/null +++ b/src/views/demo/form-design/utils/message.ts @@ -0,0 +1,19 @@ +import { useMessage } from '@/hooks/web/useMessage'; + +const { createMessage } = useMessage(); +const message = Object.assign({ + success: (msg: string) => { + createMessage.success(msg); + }, + error: (msg: string) => { + createMessage.error(msg); + }, + warning: (msg: string) => { + createMessage.warning(msg); + }, + info: (msg: string) => { + createMessage.info(msg); + }, +}); + +export default message; diff --git a/src/views/demo/h5html/index.data.ts b/src/views/demo/h5html/index.data.ts new file mode 100644 index 0000000..25c0989 --- /dev/null +++ b/src/views/demo/h5html/index.data.ts @@ -0,0 +1,47 @@ +import { BasicColumn, FormSchema } from '@/components/Table'; +import { h } from 'vue'; +import { Tag } from 'ant-design-vue'; + +export const columns: BasicColumn[] = [ + { + title: '名称', + dataIndex: 'name', + }, + { + title: '分类', + dataIndex: 'category', + }, + { + title: '类型', + dataIndex: 'formType', + width: 80, + customRender: ({ record }) => { + const status = record.formType; + const enable = ~~status === 0; + const color = enable ? '#67c23a' : '#e6a23c'; + const text = enable ? '常规表单' : '视图表单'; + return h(Tag, { color: color }, () => text); + }, + }, + { + title: '创建人', + dataIndex: 'createUserName', + }, + { + title: '创建时间', + dataIndex: 'createDate', + }, + // { + // title: '备注', + // dataIndex: 'remark', + // }, +]; + +export const searchFormSchema: FormSchema[] = [ + { + field: 'key', + label: '关键字', + component: 'Input', + colProps: { span: 8 }, + }, +]; diff --git a/src/views/demo/h5html/index.vue b/src/views/demo/h5html/index.vue new file mode 100644 index 0000000..83e0659 --- /dev/null +++ b/src/views/demo/h5html/index.vue @@ -0,0 +1,238 @@ + + + diff --git a/src/views/demo/layermanagement/components/VisitSource.vue b/src/views/demo/layermanagement/components/VisitSource.vue new file mode 100644 index 0000000..56a2e31 --- /dev/null +++ b/src/views/demo/layermanagement/components/VisitSource.vue @@ -0,0 +1,82 @@ + + diff --git a/src/views/demo/layermanagement/index.vue b/src/views/demo/layermanagement/index.vue new file mode 100644 index 0000000..bde1e00 --- /dev/null +++ b/src/views/demo/layermanagement/index.vue @@ -0,0 +1,107 @@ + + diff --git a/src/views/demo/level/Menu111.vue b/src/views/demo/level/Menu111.vue new file mode 100644 index 0000000..4850300 --- /dev/null +++ b/src/views/demo/level/Menu111.vue @@ -0,0 +1,10 @@ + + diff --git a/src/views/demo/level/Menu12.vue b/src/views/demo/level/Menu12.vue new file mode 100644 index 0000000..13c0ffb --- /dev/null +++ b/src/views/demo/level/Menu12.vue @@ -0,0 +1,10 @@ + + diff --git a/src/views/demo/level/Menu2.vue b/src/views/demo/level/Menu2.vue new file mode 100644 index 0000000..7b33de7 --- /dev/null +++ b/src/views/demo/level/Menu2.vue @@ -0,0 +1,10 @@ + + diff --git a/src/views/demo/main-out/index.vue b/src/views/demo/main-out/index.vue new file mode 100644 index 0000000..2406632 --- /dev/null +++ b/src/views/demo/main-out/index.vue @@ -0,0 +1,6 @@ + diff --git a/src/views/demo/message/msg/DetailModal.vue b/src/views/demo/message/msg/DetailModal.vue new file mode 100644 index 0000000..605c90c --- /dev/null +++ b/src/views/demo/message/msg/DetailModal.vue @@ -0,0 +1,48 @@ + + diff --git a/src/views/demo/message/msg/data.ts b/src/views/demo/message/msg/data.ts new file mode 100644 index 0000000..d618ad2 --- /dev/null +++ b/src/views/demo/message/msg/data.ts @@ -0,0 +1,86 @@ +import { BasicColumn, FormSchema } from '@/components/Table'; +import { h } from 'vue'; +import { Switch, Tag } from 'ant-design-vue'; +import { setRoleStatus } from '@/api/demo/system'; +import { useMessage } from '@/hooks/web/useMessage'; + +type CheckedType = boolean | string | number; +export const columns: BasicColumn[] = [ + { + title: '内容', + dataIndex: 'content', + }, + { + title: '状态', + dataIndex: 'isRead', + width: 80, + customRender: ({ record }) => { + const isRead = record.isRead; + const enable = ~~isRead === 1; + const color = enable ? 'green' : 'red'; + const text = enable ? '已读' : '未读'; + return h(Tag, { color: color }, () => text); + }, + }, + { + title: '时间', + dataIndex: 'createDate', + width: 180, + }, +]; + +export const searchFormSchema: FormSchema[] = [ + { + field: 'key', + label: '关键字', + component: 'Input', + colProps: { span: 8 }, + }, + { + field: 'isDelete', + component: 'Select', + label: '是否回收', + defaultValue: 0, + componentProps: { + options: [ + { + label: '否', + value: 0, + }, + { + label: '是', + value: 1, + }, + ], + }, + colProps: { span: 8 }, + }, +]; + +export const formSchema: FormSchema[] = [ + { + field: 'id', + label: '角色名称', + required: true, + component: 'Input', + ifShow: false, + }, + { + field: 'name', + label: '角色名称', + required: true, + component: 'Input', + }, + { + field: 'status', + label: '状态', + component: 'RadioButtonGroup', + defaultValue: 0, + componentProps: { + options: [ + { label: '启用', value: 0 }, + { label: '停用', value: 1 }, + ], + }, + }, +]; diff --git a/src/views/demo/message/msg/index.vue b/src/views/demo/message/msg/index.vue new file mode 100644 index 0000000..79eb932 --- /dev/null +++ b/src/views/demo/message/msg/index.vue @@ -0,0 +1,209 @@ + + + diff --git a/src/views/demo/onlineform/formCall/CallModal.vue b/src/views/demo/onlineform/formCall/CallModal.vue new file mode 100644 index 0000000..e45617c --- /dev/null +++ b/src/views/demo/onlineform/formCall/CallModal.vue @@ -0,0 +1,853 @@ + + diff --git a/src/views/demo/onlineform/formCall/CallModalFormItem/index.vue b/src/views/demo/onlineform/formCall/CallModalFormItem/index.vue new file mode 100644 index 0000000..7c50001 --- /dev/null +++ b/src/views/demo/onlineform/formCall/CallModalFormItem/index.vue @@ -0,0 +1,125 @@ + + + + + diff --git a/src/views/demo/onlineform/formCall/CreateFlow.vue b/src/views/demo/onlineform/formCall/CreateFlow.vue new file mode 100644 index 0000000..dd5d6f4 --- /dev/null +++ b/src/views/demo/onlineform/formCall/CreateFlow.vue @@ -0,0 +1,359 @@ + + + + diff --git a/src/views/demo/onlineform/formCall/CreateOrModifyComponent/index.vue b/src/views/demo/onlineform/formCall/CreateOrModifyComponent/index.vue new file mode 100644 index 0000000..8480fda --- /dev/null +++ b/src/views/demo/onlineform/formCall/CreateOrModifyComponent/index.vue @@ -0,0 +1,44 @@ + + + + + diff --git a/src/views/demo/onlineform/formCall/ImportModal/ShowErrorList/index.vue b/src/views/demo/onlineform/formCall/ImportModal/ShowErrorList/index.vue new file mode 100644 index 0000000..dafa932 --- /dev/null +++ b/src/views/demo/onlineform/formCall/ImportModal/ShowErrorList/index.vue @@ -0,0 +1,44 @@ + + + + + diff --git a/src/views/demo/onlineform/formCall/ImportModal/index.vue b/src/views/demo/onlineform/formCall/ImportModal/index.vue new file mode 100644 index 0000000..2e245c4 --- /dev/null +++ b/src/views/demo/onlineform/formCall/ImportModal/index.vue @@ -0,0 +1,124 @@ + + + + + diff --git a/src/views/demo/onlineform/formCall/InfoCallModal/index.vue b/src/views/demo/onlineform/formCall/InfoCallModal/index.vue new file mode 100644 index 0000000..9e3eb61 --- /dev/null +++ b/src/views/demo/onlineform/formCall/InfoCallModal/index.vue @@ -0,0 +1,304 @@ + + + + + diff --git a/src/views/demo/onlineform/formCall/InfoCallModal/video.png b/src/views/demo/onlineform/formCall/InfoCallModal/video.png new file mode 100644 index 0000000..ba615a2 Binary files /dev/null and b/src/views/demo/onlineform/formCall/InfoCallModal/video.png differ diff --git a/src/views/demo/onlineform/formCall/MapForm.vue b/src/views/demo/onlineform/formCall/MapForm.vue new file mode 100644 index 0000000..ef46a24 --- /dev/null +++ b/src/views/demo/onlineform/formCall/MapForm.vue @@ -0,0 +1,791 @@ + + + + \ No newline at end of file diff --git a/src/views/demo/onlineform/formCall/ShowFormModal/FormItem/index.vue b/src/views/demo/onlineform/formCall/ShowFormModal/FormItem/index.vue new file mode 100644 index 0000000..b36cb93 --- /dev/null +++ b/src/views/demo/onlineform/formCall/ShowFormModal/FormItem/index.vue @@ -0,0 +1,18 @@ + + + + + diff --git a/src/views/demo/onlineform/formCall/ShowFormModal/index.vue b/src/views/demo/onlineform/formCall/ShowFormModal/index.vue new file mode 100644 index 0000000..422dbe2 --- /dev/null +++ b/src/views/demo/onlineform/formCall/ShowFormModal/index.vue @@ -0,0 +1,411 @@ + + + + + + diff --git a/src/views/demo/onlineform/formCall/index.data.ts b/src/views/demo/onlineform/formCall/index.data.ts new file mode 100644 index 0000000..dee5253 --- /dev/null +++ b/src/views/demo/onlineform/formCall/index.data.ts @@ -0,0 +1,43 @@ +import { BasicColumn, FormSchema } from '@/components/Table'; +import { h } from 'vue'; +import { Tag } from 'ant-design-vue'; + +export const columns: BasicColumn[] = [ + { + title: '名称', + dataIndex: 'name', + }, + { + title: '分类', + dataIndex: 'category', + }, + { + title: '类型', + dataIndex: 'formType', + width: 80, + customRender: ({ record }) => { + const status = record.formType; + const enable = ~~status === 0; + const color = enable ? '#67c23a' : '#e6a23c'; + const text = enable ? '常规表单' : '视图表单'; + return h(Tag, { color: color }, () => text); + }, + }, + { + title: '创建人', + dataIndex: 'createUserName', + }, + { + title: '创建时间', + dataIndex: 'createDate', + }, +]; + +export const searchFormSchema: FormSchema[] = [ + { + field: 'key', + label: '关键字', + component: 'Input', + colProps: { span: 8 }, + }, +]; diff --git a/src/views/demo/onlineform/formCall/index.vue b/src/views/demo/onlineform/formCall/index.vue new file mode 100644 index 0000000..323100f --- /dev/null +++ b/src/views/demo/onlineform/formCall/index.vue @@ -0,0 +1,1190 @@ + + + diff --git a/src/views/demo/onlineform/formCall/utils.ts b/src/views/demo/onlineform/formCall/utils.ts new file mode 100644 index 0000000..cf1d9ed --- /dev/null +++ b/src/views/demo/onlineform/formCall/utils.ts @@ -0,0 +1,296 @@ +import { useMessage } from '@/hooks/web/useMessage'; +import { useUserStore } from '@/store/modules/user'; +import { defHttp } from '@/utils/http/axios'; + +// utils.ts +let c_formModalVisible: Boolean = false; +let c_isUpdate = true; +let c_isDetail = true; +let c_getTitle = ''; +let c_primaryQuery = ''; +let c_addQuery: any = []; +let c_formColumns: any = []; +let c_tabsColumns: any = []; +let c_flowCode = ''; +let c_formData = {}; +let c_subTableId = null; +let c_subTableColumns: any = []; +let c_subTableData: any = []; +let c_subTableList: any = []; +let c_scrollValue = ''; +let c_cardLayout: any = []; +let c_createOrModifyList: any = []; +let c_buttonLayout: any = []; +let c_gridButtonLayout: any = []; +let c_record: any = {}; +let c_cardValues: any = {}; + +const { createMessage } = useMessage(); +const userStore = useUserStore(); +const userInfo: any = userStore.getUserInfo; + +// 通过field获取组件 +function getComponentByFiled(data: string): any { + return c_formColumns.find(item => item.field === data); +} +function getChildComponentByFiled(data: string): any { + return c_subTableData.find(item => item.field === data); +} +function setChildComponentByFiled(childComponet: any, field: string): any { + c_formColumns.forEach((item, index1) => { + if (item.columns) { + item.columns[0].children.forEach((i, index2) => { + if (i.field == field) { + c_formColumns[index1].columns[0].children[index2] = childComponet; + } + }); + } + }); +} +export const utils = { + setCallModalData: function setCallModalData(data: any) { + c_formModalVisible = data.formModalVisible.value; + c_isUpdate = data.isUpdate.value; + c_isDetail = data.isDetail.value; + c_getTitle = data.getTitle.value; + c_primaryQuery = data.primaryQuery.value; + c_addQuery = data.addQuery.value; + c_formColumns = data.formColumns.value; + c_tabsColumns = data.tabsColumns.value; + c_flowCode = data.flowCode.value; + c_formData = data.formData; + c_subTableId = data.subTableId.value; + c_subTableColumns = data.subTableColumns.value; + c_subTableData = data.subTableData.value; + c_subTableList = data.subTableList.value; + c_scrollValue = data.scrollValue.value; + c_cardLayout = data.cardLayout.value; + c_createOrModifyList = data.createOrModifyList.value; + c_buttonLayout = data.buttonLayout.value; + c_gridButtonLayout = data.gridButtonLayout.value; + c_record = data.record; + c_cardValues = data.cardValues.value; + }, + formModalVisible: (): Boolean => { + return c_formModalVisible; + }, + isUpdate: (): Boolean => { + return c_isUpdate; + }, + isDetail: (): Boolean => { + return c_isDetail; + }, + getTitle: (): string => { + return c_getTitle; + }, + primaryQuery: (): string => { + return c_primaryQuery; + }, + addQuery: (): any => { + return c_addQuery; + }, + formColumns: (): any => { + return c_formColumns; + }, + tabsColumns: (): any => { + return c_tabsColumns; + }, + flowCode: (): string => { + return c_flowCode; + }, + formData: (): {} => { + return c_formData; + }, + subTableId: (): any => { + return c_subTableId; + }, + subTableColumns: (): any => { + return c_subTableColumns; + }, + subTableData: (): any => { + return c_subTableData; + }, + subTableList: (): any => { + return c_subTableList; + }, + scrollValue: (): string => { + return c_scrollValue; + }, + cardLayout: (): any => { + return c_cardLayout; + }, + createOrModifyList: (): any => { + return c_createOrModifyList; + }, + buttonLayout: (): any => { + return c_buttonLayout; + }, + gridButtonLayout: (): any => { + return c_gridButtonLayout; + }, + record: (): any => { + return c_record; + }, + cardValues: (): any => { + return c_cardValues; + }, + // 数据----------------------------- + // 获取主表数据 + getValue: (field: any): any => { + return c_record[field]; + }, + // 设置主表数据 + setValue: (field: any, value: any): any => { + c_record[field] = value; + return c_record; + }, + // 获取子表数据 + getChildValue: (field: any): any => { + if (field == '') { + return c_subTableList; + } else { + const res: any = []; + c_subTableList.forEach((v) => { + res.push(v[field]); + }); + return res; + } + }, + // 添加子表数据 + addChildValue: (data: any): any => { + if (typeof data == 'object') { + if (Array.isArray(data)) { + data.forEach((d) => { + c_subTableList.push(d); + }); + } else { + c_subTableList.push(data); + } + } + return c_subTableList; + }, + // 修改子表数据 + updateChildValue: (field: string, oldValue: string, newValue: string): any => { + const c_subTableList_temp: any = []; + c_subTableList.forEach((sub) => { + if (sub[field] == oldValue) { + sub[field] = newValue; + } + c_subTableList_temp.push(sub); + }); + c_subTableList = c_subTableList_temp; + return c_subTableList; + }, + // 删除子表数据 + deleteChildValue: (field: string, value: string): any => { + const c_subTableList_temp: any = []; + c_subTableList.forEach((sub) => { + if (sub[field] != value) { + c_subTableList_temp.push(sub); + } + }); + c_subTableList = c_subTableList_temp; + return c_subTableList; + }, + // 组件----------------------------- + // 获取组件 + getComponent: (field: any): any => { + return getComponentByFiled(field) || getChildComponentByFiled(field); + }, + // 隐藏与否 + setHide: (field: any, hideStatus: Boolean): any => { + const componet: any = getComponentByFiled(field); + if (componet) { + componet.ifShow = hideStatus; + c_formColumns.forEach((item, index) => { + if (item.filed == field) { + c_formColumns[index] = componet; + } + }); + } else { + const childComponet: any = getChildComponentByFiled(field); + if (childComponet) { + childComponet.ifShow = hideStatus; + setChildComponentByFiled(childComponet, field); + } + } + return c_formColumns; + }, + // 禁用与否 + setDisabled: (field: any, disabledStatus: Boolean): any => { + const componet: any = getComponentByFiled(field); + if (componet) { + componet.dynamicDisabled = disabledStatus; + c_formColumns.forEach((item, index) => { + if (item.filed == field) { + c_formColumns[index] = componet; + } + }); + } else { + const childComponet: any = getChildComponentByFiled(field); + if (childComponet) { + childComponet.dynamicDisabled = disabledStatus; + setChildComponentByFiled(childComponet, field); + } + } + return c_formColumns; + }, + // 必填与否 + setRequired: (field: any, requiredStatus: Boolean): any => { + const componet: any = getComponentByFiled(field); + if (componet) { + componet.required = requiredStatus; + c_formColumns.forEach((item, index) => { + if (item.filed == field) { + c_formColumns[index] = componet; + } + }); + } else { + const childComponet: any = getChildComponentByFiled(field); + if (childComponet) { + childComponet.required = requiredStatus; + setChildComponentByFiled(childComponet, field); + } + } + return c_formColumns; + }, + // 功能----------------------------- + // 提示消息 + message: (message: string, type: string = 'info') => { + if (type == 'success') { + createMessage.success(message); + } else if (type == 'error') { + createMessage.error(message); + } else if (type == 'warn') { + createMessage.warn(message); + } else { + createMessage.info(message); + } + }, + // 获取登录者信息 + loginUser: () => { + return { account: userInfo.account, name: userInfo.name }; + }, + // 回调方法----------------------------- + // get请求 + httpGet: (api: string, params: any) => { + return defHttp.get({ + url: api, + params, + }); + }, + // post请求 + httpPost: (api: string, params: any) => { + return defHttp.post({ + url: api, + params, + }); + }, + // put请求 + httpPut: (api: string, params: any) => { + return defHttp.put({ + url: api, + params, + }); + }, +}; diff --git a/src/views/demo/onlineform/formModule/FormModal.vue b/src/views/demo/onlineform/formModule/FormModal.vue new file mode 100644 index 0000000..7f1c30e --- /dev/null +++ b/src/views/demo/onlineform/formModule/FormModal.vue @@ -0,0 +1,295 @@ + + + + diff --git a/src/views/demo/onlineform/formModule/FormTree.vue b/src/views/demo/onlineform/formModule/FormTree.vue new file mode 100644 index 0000000..0062994 --- /dev/null +++ b/src/views/demo/onlineform/formModule/FormTree.vue @@ -0,0 +1,52 @@ + + diff --git a/src/views/demo/onlineform/formModule/config/btns.vue b/src/views/demo/onlineform/formModule/config/btns.vue new file mode 100644 index 0000000..c13dec1 --- /dev/null +++ b/src/views/demo/onlineform/formModule/config/btns.vue @@ -0,0 +1,146 @@ + + diff --git a/src/views/demo/onlineform/formModule/config/columns.vue b/src/views/demo/onlineform/formModule/config/columns.vue new file mode 100644 index 0000000..16b5f8c --- /dev/null +++ b/src/views/demo/onlineform/formModule/config/columns.vue @@ -0,0 +1,130 @@ + + + + + diff --git a/src/views/demo/onlineform/formModule/config/config.data.ts b/src/views/demo/onlineform/formModule/config/config.data.ts new file mode 100644 index 0000000..6e945a2 --- /dev/null +++ b/src/views/demo/onlineform/formModule/config/config.data.ts @@ -0,0 +1,48 @@ +import { BasicColumn } from '@/components/Table'; + +// 步骤一:基本配置 scheme 部分 添加数据库表(请先选择数据库) +export function columns(): BasicColumn[] { + return [ + { title: '列名', dataIndex: 'label', width: 150 }, + { title: '宽度', dataIndex: 'width', width: 120, align: 'center' }, + { title: '自适应宽度', dataIndex: 'isMinWidth', width: 100, align: 'center' }, + { title: '对齐', dataIndex: 'align', width: 100, align: 'center' }, + ]; +} + +export function querys(): BasicColumn[] { + return [{ title: '查询字段名', dataIndex: 'label', width: '400' }]; +} + +export const btns: BasicColumn[] = [ + { + title: 'ID', + dataIndex: 'prop', + width: 120, + }, + { + title: '行按钮', + dataIndex: 'isRowBtn', + width: 80, + }, + { + title: '创建流程', + dataIndex: 'isWFlow', + width: 120, + }, + { + title: '流程模版', + dataIndex: 'wFlowCode', + width: 150, + }, + { + title: '权限标识', + dataIndex: 'class', + width: 120, + }, + { + title: '排序', + dataIndex: 'sort', + width: 80, + }, +]; diff --git a/src/views/demo/onlineform/formModule/config/layout.vue b/src/views/demo/onlineform/formModule/config/layout.vue new file mode 100644 index 0000000..0e87bec --- /dev/null +++ b/src/views/demo/onlineform/formModule/config/layout.vue @@ -0,0 +1,109 @@ + + + diff --git a/src/views/demo/onlineform/formModule/config/leftTree.vue b/src/views/demo/onlineform/formModule/config/leftTree.vue new file mode 100644 index 0000000..97c8da5 --- /dev/null +++ b/src/views/demo/onlineform/formModule/config/leftTree.vue @@ -0,0 +1,335 @@ + + + diff --git a/src/views/demo/onlineform/formModule/config/maps.vue b/src/views/demo/onlineform/formModule/config/maps.vue new file mode 100644 index 0000000..ed95e71 --- /dev/null +++ b/src/views/demo/onlineform/formModule/config/maps.vue @@ -0,0 +1,528 @@ + + + + diff --git a/src/views/demo/onlineform/formModule/config/query.vue b/src/views/demo/onlineform/formModule/config/query.vue new file mode 100644 index 0000000..96be3c8 --- /dev/null +++ b/src/views/demo/onlineform/formModule/config/query.vue @@ -0,0 +1,111 @@ + + + + + diff --git a/src/views/demo/onlineform/formModule/formModule.data.ts b/src/views/demo/onlineform/formModule/formModule.data.ts new file mode 100644 index 0000000..a792729 --- /dev/null +++ b/src/views/demo/onlineform/formModule/formModule.data.ts @@ -0,0 +1,302 @@ +import { BasicColumn, FormSchema } from '@/components/Table'; +import { h } from 'vue'; +import { Switch } from 'ant-design-vue'; +import { fun_UpdateModuleState } from '@/api/demo/formModule'; +import { useMessage } from '@/hooks/web/useMessage'; +import { getMenuList } from '@/api/demo/system'; + +type CheckedType = boolean | string | number; + +export const formModuleColumns: BasicColumn[] = [ + { + title: '编码', + dataIndex: 'code', + width: 160, + }, + { + title: '名称', + dataIndex: 'name', + width: 160, + }, + { + title: '上级功能', + dataIndex: 'pmoduleId', + width: 160, + }, + { + title: '状态', + dataIndex: 'enabledMark', + width: 80, + customRender: ({ record }) => { + return h(Switch, { + checked: record.enabledMark === 1, + checkedChildren: '启用', + unCheckedChildren: '停用', + loading: record.pendingStatus, + onChange(checked: CheckedType) { + record.pendingStatus = true; + const newStatus = checked ? 1 : 0; + const { createMessage } = useMessage(); + fun_UpdateModuleState({ id: record.id, state: newStatus }) + .then(() => { + record.enabledMark = newStatus; + createMessage.success(`状态更新成功`); + }) + .catch(() => { + createMessage.error('状态更新失败'); + }) + .finally(() => { + record.pendingStatus = false; + }); + }, + }); + }, + }, + { + title: '创建人', + dataIndex: 'createUserName', + width: 120, + }, + { + title: '创建时间', + dataIndex: 'createDate', + width: 160, + }, + { + title: 'id', + dataIndex: 'id', + ifShow: false, + }, + { + title: 'code', + dataIndex: 'code', + ifShow: false, + }, + { + title: 'formCode', + dataIndex: 'formCode', + ifShow: false, + }, + { + title: 'formVerison', + dataIndex: 'formVerison', + ifShow: false, + }, + { + title: 'icon', + dataIndex: 'icon', + ifShow: false, + }, + { + title: 'type', + dataIndex: 'type', + ifShow: false, + }, + { + title: 'moduleId', + dataIndex: 'moduleId', + ifShow: false, + }, + { + title: 'sortCode', + dataIndex: 'sortCode', + ifShow: false, + }, + { + title: 'description', + dataIndex: 'description', + ifShow: false, + }, + { + title: 'createUserId', + dataIndex: 'createUserId', + ifShow: false, + }, + { + title: 'modifyDate', + dataIndex: 'modifyDate', + ifShow: false, + }, + { + title: 'modifyUserId', + dataIndex: 'modifyUserId', + ifShow: false, + }, + { + title: 'modifyUserName', + dataIndex: 'modifyUserName', + ifShow: false, + }, + { + title: 'scheme', + dataIndex: 'scheme', + ifShow: false, + }, + { + title: 'keyWord', + dataIndex: 'keyWord', + ifShow: false, + }, + { + title: 'tenantId', + dataIndex: 'tenantId', + ifShow: false, + }, + { + title: 'isMain', + dataIndex: 'isMain', + ifShow: false, + }, +]; + +export const searchFormSchema: FormSchema[] = [ + { + field: 'keyword', + label: '关键字', + component: 'Input', + colProps: { span: 8 }, + }, +]; + +export const formSchema: FormSchema[] = [ + { + field: 'code', + component: 'Input', + label: '编号', + colProps: { + span: 24, + }, + defaultValue: '', + required: true, + componentProps: { + placeholder: '请输入', + }, + }, + { + field: 'name', + component: 'Input', + label: '名称', + colProps: { + span: 24, + }, + defaultValue: '', + required: true, + componentProps: { + placeholder: '请输入', + }, + }, + { + field: 'icon', + component: 'IconPicker', + label: '图标', + colProps: { + span: 24, + }, + defaultValue: '', + required: true, + componentProps: { + placeholder: '请输入', + }, + }, + { + field: 'formCode', + component: 'Input', + label: '表单选择', + colProps: { + span: 24, + }, + defaultValue: '', + required: true, + componentProps: { + placeholder: '请输入', + }, + }, + { + field: 'formVerison', + component: 'ApiSelect', + label: '表单版本', + required: true, + colProps: { + span: 24, + }, + }, + { + field: 'pmoduleId', + component: 'ApiTreeSelect', + label: '上级', + colProps: { + span: 24, + }, + componentProps: () => { + return { + api: getMenuList, + // 接口返回数据 + resultField: 'result', + labelField: 'name', + valueField: 'id', + }; + }, + }, + { + field: 'enabledMark', + label: '状态', + component: 'RadioButtonGroup', + defaultValue: 1, + componentProps: { + options: [ + { label: '是', value: 1 }, + { label: '否', value: 0 }, + ], + }, + }, + { + field: 'sortCode', + label: '排序', + component: 'InputNumber', + defaultValue: 0, + colProps: { lg: 24, md: 24 }, + }, + { + field: 'description', + component: 'InputTextArea', + label: '描述', + colProps: { + span: 24, + }, + defaultValue: '', + componentProps: { + placeholder: '请输入', + }, + }, +]; + +export const searchFormSchema_Modal: FormSchema[] = [ + { + field: 'keyword', + label: '关键字', + component: 'Input', + colProps: { span: 12 }, + }, +]; + +export const modalColumns: BasicColumn[] = [ + { + title: '名称', + dataIndex: 'name', + width: 200, + }, + { + dataIndex: 'scheme', + ifShow: false, + }, + { + title: '分类', + dataIndex: 'category', + width: 80, + }, + { + title: '操作', + dataIndex: 'action', + width: 80, + }, +]; diff --git a/src/views/demo/onlineform/formModule/index.vue b/src/views/demo/onlineform/formModule/index.vue new file mode 100644 index 0000000..f11595b --- /dev/null +++ b/src/views/demo/onlineform/formModule/index.vue @@ -0,0 +1,199 @@ + + diff --git a/src/views/demo/onlineform/formModule/modalDesign.vue b/src/views/demo/onlineform/formModule/modalDesign.vue new file mode 100644 index 0000000..e0e711e --- /dev/null +++ b/src/views/demo/onlineform/formModule/modalDesign.vue @@ -0,0 +1,428 @@ + + + diff --git a/src/views/demo/onlineform/formModule/modalForm-Modal.vue b/src/views/demo/onlineform/formModule/modalForm-Modal.vue new file mode 100644 index 0000000..2e75698 --- /dev/null +++ b/src/views/demo/onlineform/formModule/modalForm-Modal.vue @@ -0,0 +1,256 @@ + + + diff --git a/src/views/demo/onlineform/formModule/modalForm.vue b/src/views/demo/onlineform/formModule/modalForm.vue new file mode 100644 index 0000000..bddd77c --- /dev/null +++ b/src/views/demo/onlineform/formModule/modalForm.vue @@ -0,0 +1,363 @@ + + + + + diff --git a/src/views/demo/onlineform/formScheme/FormSchemeDrawer.vue b/src/views/demo/onlineform/formScheme/FormSchemeDrawer.vue new file mode 100644 index 0000000..1367551 --- /dev/null +++ b/src/views/demo/onlineform/formScheme/FormSchemeDrawer.vue @@ -0,0 +1,83 @@ + + diff --git a/src/views/demo/onlineform/formScheme/FormSchemeTree.vue b/src/views/demo/onlineform/formScheme/FormSchemeTree.vue new file mode 100644 index 0000000..bda0abb --- /dev/null +++ b/src/views/demo/onlineform/formScheme/FormSchemeTree.vue @@ -0,0 +1,112 @@ + + diff --git a/src/views/demo/onlineform/formScheme/formScheme.data.ts b/src/views/demo/onlineform/formScheme/formScheme.data.ts new file mode 100644 index 0000000..3e6f094 --- /dev/null +++ b/src/views/demo/onlineform/formScheme/formScheme.data.ts @@ -0,0 +1,215 @@ +import { BasicColumn, FormSchema } from '@/components/Table'; +import { h } from 'vue'; +import { Tag, Switch } from 'ant-design-vue'; +import { functionUpdateState } from '@/api/demo/formScheme'; +import { useMessage } from '@/hooks/web/useMessage'; + +type CheckedType = boolean | string | number; + +export const columns: BasicColumn[] = [ + { + title: '名称', + dataIndex: 'name', + width: 120, + }, + { + title: '分类', + dataIndex: 'category', + width: 80, + }, + { + title: '类型', + dataIndex: 'formType', + width: 80, + customRender: ({ record }) => { + const formType = record.formType; + const enable = ~~formType === 0; + const color = enable ? 'green' : 'yellow'; + const text = enable ? '常规表单' : '视图表单'; + return h(Tag, { color: color }, () => text); + }, + }, + { + title: '状态', + dataIndex: 'enabledMark', + width: 80, + customRender: ({ record }) => { + if (!record.type || record.type === 2) { + const color = 'blue'; + const text = '草稿'; + return h(Tag, { color: color }, () => text); + } else { + return h(Switch, { + checked: record.enabledMark === 1, + checkedChildren: '启用', + unCheckedChildren: '停用', + loading: record.pendingStatus, + onChange(checked: CheckedType) { + record.pendingStatus = true; + const newStatus = checked ? 1 : 0; + const { createMessage } = useMessage(); + functionUpdateState({ id: record.id, state: newStatus }) + // , state: newStatus + .then(() => { + record.enabledMark = newStatus; + createMessage.success(`已成功修改表单状态`); + }) + .catch(() => { + createMessage.error('修改表单状态失败'); + }) + .finally(() => { + record.pendingStatus = false; + }); + }, + }); + } + }, + }, + { + title: '创建人', + dataIndex: 'createUserName', + width: 80, + }, + { + title: '创建时间', + dataIndex: 'createDate', + width: 120, + }, +]; + +const colProps = { + span: 24, +}; + +export const searchFormSchema: FormSchema[] = [ + { + field: 'keyWord', + label: '名称', + component: 'Input', + colProps: { span: 8 }, + }, +]; + +export const formSchema: FormSchema[] = [ + { + field: 'itemDetailId', + component: 'Input', + ifShow: false, + }, + { + field: 'itemId', + label: '项目ID', + component: 'Input', + ifShow: false, + }, + { + field: 'parentId', + label: '上级', + component: 'TreeSelect', + componentProps: { + fieldNames: { + label: 'itemName', + key: 'itemId', + value: 'itemValue', + }, + getPopupContainer: () => document.body, + }, + colProps, + }, + { + field: 'itemCode', + component: 'Input', + ifShow: false, + }, + { + field: 'itemName', + label: '项目名', + component: 'Input', + required: true, + colProps, + }, + { + field: 'itemValue', + label: '项目值', + component: 'Input', + required: true, + colProps, + }, + { + field: 'quickQuery', + component: 'Input', + ifShow: false, + }, + { + field: 'simpleSpelling', + component: 'Input', + ifShow: false, + }, + { + field: 'isDefault', + component: 'Input', + ifShow: false, + }, + { + field: 'sortCode', + label: '排序', + component: 'InputNumber', + required: true, + colProps, + }, + { + field: 'deleteMark', + component: 'Input', + ifShow: false, + }, + { + field: 'enabledMark', + label: '状态', + component: 'Switch', + colProps, + ifShow: false, + render: (scope) => { + return h('Switch', { + props: { + value: scope.model?.enabledMark === 1, + }, + }); + }, + }, + { + field: 'description', + label: '备注', + component: 'InputTextArea', + colProps, + }, + { + field: 'createDate', + component: 'Input', + ifShow: false, + }, + { + field: 'createUserId', + component: 'Input', + ifShow: false, + }, + { + field: 'createUserName', + component: 'Input', + ifShow: false, + }, + { + field: 'modifyDate', + component: 'Input', + ifShow: false, + }, + { + field: 'modifyUserId', + component: 'Input', + ifShow: false, + }, + { + field: 'modifyUserName', + component: 'Input', + ifShow: false, + }, +]; diff --git a/src/views/demo/onlineform/formScheme/index.vue b/src/views/demo/onlineform/formScheme/index.vue new file mode 100644 index 0000000..b6e6de1 --- /dev/null +++ b/src/views/demo/onlineform/formScheme/index.vue @@ -0,0 +1,268 @@ + + diff --git a/src/views/demo/onlineform/formScheme/modal/HistoryModal.vue b/src/views/demo/onlineform/formScheme/modal/HistoryModal.vue new file mode 100644 index 0000000..4f6b799 --- /dev/null +++ b/src/views/demo/onlineform/formScheme/modal/HistoryModal.vue @@ -0,0 +1,112 @@ + + diff --git a/src/views/demo/onlineform/formScheme/modal/PreviewModal.vue b/src/views/demo/onlineform/formScheme/modal/PreviewModal.vue new file mode 100644 index 0000000..a69c2f0 --- /dev/null +++ b/src/views/demo/onlineform/formScheme/modal/PreviewModal.vue @@ -0,0 +1,17 @@ + + diff --git a/src/views/demo/onlineform/formScheme/modal/modelData.ts b/src/views/demo/onlineform/formScheme/modal/modelData.ts new file mode 100644 index 0000000..9128526 --- /dev/null +++ b/src/views/demo/onlineform/formScheme/modal/modelData.ts @@ -0,0 +1,69 @@ +import { BasicColumn } from '@/components/Table'; +import { h } from 'vue'; +import { Tag } from 'ant-design-vue'; + +export function getHistoryColumns(): BasicColumn[] { + return [ + { + title: 'id', + dataIndex: 'id', + ifShow: false, + }, + { + title: 'schemeInfoId', + dataIndex: 'schemeInfoId', + ifShow: false, + }, + { + title: 'scheme', + dataIndex: 'scheme', + ifShow: false, + }, + { + title: 'createUserId', + dataIndex: 'createUserId', + ifShow: false, + }, + { + title: '创建人', + width: 150, + dataIndex: 'createUserName', + }, + { + title: '创建时间', + width: 150, + dataIndex: 'createDate', + }, + { + title: 'tenantId', + dataIndex: 'tenantId', + ifShow: false, + }, + { + title: '状态', + dataIndex: 'type', + width: 80, + customRender: ({ record }) => { + if (!record.type || record.type === 2) { + const color = 'gray'; + const text = '草稿'; + return h(Tag, { color: color }, () => text); + } else { + const color = 'green'; + const text = '正式'; + return h(Tag, { color: color }, () => text); + } + }, + }, + { + title: '当前版本', + dataIndex: 'currentVersion', + width: 80, + }, + { + title: '操作', + dataIndex: 'action', + width: 80, + }, + ]; +} diff --git a/src/views/demo/onlineform/formdesign/FormModal.vue b/src/views/demo/onlineform/formdesign/FormModal.vue new file mode 100644 index 0000000..47d4e85 --- /dev/null +++ b/src/views/demo/onlineform/formdesign/FormModal.vue @@ -0,0 +1,650 @@ + + + diff --git a/src/views/demo/onlineform/formdesign/FormSchemeDrawer.vue b/src/views/demo/onlineform/formdesign/FormSchemeDrawer.vue new file mode 100644 index 0000000..1367551 --- /dev/null +++ b/src/views/demo/onlineform/formdesign/FormSchemeDrawer.vue @@ -0,0 +1,83 @@ + + diff --git a/src/views/demo/onlineform/formdesign/FormSchemeTree.vue b/src/views/demo/onlineform/formdesign/FormSchemeTree.vue new file mode 100644 index 0000000..3917177 --- /dev/null +++ b/src/views/demo/onlineform/formdesign/FormSchemeTree.vue @@ -0,0 +1,113 @@ + + diff --git a/src/views/demo/onlineform/formdesign/form.data.ts b/src/views/demo/onlineform/formdesign/form.data.ts new file mode 100644 index 0000000..25c0989 --- /dev/null +++ b/src/views/demo/onlineform/formdesign/form.data.ts @@ -0,0 +1,47 @@ +import { BasicColumn, FormSchema } from '@/components/Table'; +import { h } from 'vue'; +import { Tag } from 'ant-design-vue'; + +export const columns: BasicColumn[] = [ + { + title: '名称', + dataIndex: 'name', + }, + { + title: '分类', + dataIndex: 'category', + }, + { + title: '类型', + dataIndex: 'formType', + width: 80, + customRender: ({ record }) => { + const status = record.formType; + const enable = ~~status === 0; + const color = enable ? '#67c23a' : '#e6a23c'; + const text = enable ? '常规表单' : '视图表单'; + return h(Tag, { color: color }, () => text); + }, + }, + { + title: '创建人', + dataIndex: 'createUserName', + }, + { + title: '创建时间', + dataIndex: 'createDate', + }, + // { + // title: '备注', + // dataIndex: 'remark', + // }, +]; + +export const searchFormSchema: FormSchema[] = [ + { + field: 'key', + label: '关键字', + component: 'Input', + colProps: { span: 8 }, + }, +]; diff --git a/src/views/demo/onlineform/formdesign/form/DataObject.vue b/src/views/demo/onlineform/formdesign/form/DataObject.vue new file mode 100644 index 0000000..65c4a52 --- /dev/null +++ b/src/views/demo/onlineform/formdesign/form/DataObject.vue @@ -0,0 +1,182 @@ + + + diff --git a/src/views/demo/onlineform/formdesign/form/dataobject.data.ts b/src/views/demo/onlineform/formdesign/form/dataobject.data.ts new file mode 100644 index 0000000..c530524 --- /dev/null +++ b/src/views/demo/onlineform/formdesign/form/dataobject.data.ts @@ -0,0 +1,38 @@ +import { BasicColumn, FormSchema } from '@/components/Table'; +import { h } from 'vue'; +import { Tag } from 'ant-design-vue'; + +export const columns: BasicColumn[] = [ + { + title: '表名', + dataIndex: 'tableName', + }, + { + title: '备注', + dataIndex: 'description', + }, + { + title: '状态', + dataIndex: 'stateSlot', + key: 'stateSlot', + }, +]; +export const searchFormSchema: FormSchema[] = [ + { + field: 'key', + label: '关键字', + component: 'Input', + colProps: { span: 8 }, + }, +]; + +export const importColumns: BasicColumn[] = [ + { + title: '表名', + dataIndex: 'name', + }, + { + title: '说明', + dataIndex: 'description', + }, +]; diff --git a/src/views/demo/onlineform/formdesign/form/index.data.ts b/src/views/demo/onlineform/formdesign/form/index.data.ts new file mode 100644 index 0000000..e1f9866 --- /dev/null +++ b/src/views/demo/onlineform/formdesign/form/index.data.ts @@ -0,0 +1,322 @@ +import { BasicColumn, FormSchema } from '@/components/Table'; +import { getFormsTypeList, getDataBaseCodeList } from '@/api/formdesign/index'; +import { h } from 'vue'; +import { Tag } from 'ant-design-vue'; + +export const connectColumns: BasicColumn[] = [ + { + title: '名称', + dataIndex: 'fname', + width: 100, + key: 'fname', + }, + { + title: '表名', + dataIndex: 'name', + width: 120, + }, + { + title: '比较字段', + width: 150, + key: 'cfield', + dataIndex: 'cfield', + }, + { + title: '外键', + width: 150, + key: 'field', + dataIndex: 'field', + }, + { + title: '关联表', + width: 150, + key: 'relationName', + dataIndex: 'relationName', + }, + { + title: '关联主键', + width: 150, + key: 'relationField', + dataIndex: 'relationField', + }, +]; + +export const viewsColumns: BasicColumn[] = [ + { + title: '类别', + dataIndex: 'type', + width: 50, + customRender: ({ record }) => { + const status = record.type; + let enable; + if (status == 'main') { + enable = true; + } else { + enable = false; + } + const color = enable ? '#67c23a' : '#e6a23c'; + const text = enable ? '主' : '子'; + return h(Tag, { color: color }, () => text); + }, + }, + { + title: '名称', + dataIndex: 'name', + width: 150, + }, + { + title: '关联字段', + width: 150, + key: 'relationFieldConnect', + dataIndex: 'relationFieldConnect', + }, +]; + +export const columns: BasicColumn[] = [ + { + title: '类别', + dataIndex: 'type', + width: 50, + customRender: ({ record }) => { + const status = record.type; + let enable; + if (status == 'main') { + enable = true; + } else { + enable = false; + } + const color = enable ? '#67c23a' : '#e6a23c'; + const text = enable ? '主表' : '子表'; + return h(Tag, { color: color }, () => text); + }, + }, + { + title: '表名', + dataIndex: 'name', + width: 140, + }, + { + title: '外键', + width: 130, + key: 'fieldAction', + dataIndex: 'fieldAction', + }, + { + title: '关联表', + width: 130, + key: 'relationTabAction', + dataIndex: 'relationTabAction', + }, + { + title: '关联主键', + width: 130, + key: 'relationFieldAction', + dataIndex: 'relationFieldAction', + }, +]; +const isButton = (formType: number) => formType === 0; +const isButton2 = (formType: number) => formType === 1; +export const formSchema: FormSchema[] = [ + { + field: 'id', + component: 'Input', + label: 'id', + ifShow: false, + }, + { + field: 'schemeId', + component: 'Input', + label: 'schemeId', + ifShow: false, + }, + { + field: 'name', + component: 'Input', + label: '名称', + colProps: { + span: 24, + }, + defaultValue: '', + required: true, + componentProps: { + placeholder: '请输入', + }, + }, + { + field: 'category', + component: 'ApiSelect', + label: '分类', + required: true, + colProps: { + span: 24, + }, + componentProps: () => { + return { + api: getFormsTypeList, + params: { + code: 'FormSort', + }, + resultField: '', + labelField: 'itemName', + valueField: 'itemValue', + }; + }, + }, + { + field: 'DbCode', + component: 'ApiTreeSelect', + label: '数据库', + required: true, + colProps: { + span: 24, + }, + componentProps: { + api: () => + getDataBaseCodeList({}).then((data: Recordable) => { + return new Promise((resolve) => { + resolve(data); + }); + }), + labelField: 'text', + valueField: 'value', + async: true, + // onChange: (e, v) => { + // console.log('ApiTreeSelect====>:', e, v); + // }, + onLoadData: ({ treeData, resolve, treeNode }) => { + setTimeout(() => { + const children: Recordable[] = []; + treeData.value.forEach((item) => { + if (item.id == treeNode.id) { + if (item.childNodes) { + item.childNodes.forEach((val) => { + children.push({ + text: val.text, + value: val.value, + }); + }); + } + } + }); + children.forEach((item) => { + item.isLeaf = false; + item.children = []; + }); + treeNode.dataRef.children = children; + treeData.value = [...treeData.value]; + resolve(); + return; + }, 300); + }, + }, + }, + { + field: 'enabledMark', + label: '状态', + component: 'RadioButtonGroup', + defaultValue: 1, + componentProps: { + options: [ + { label: '是', value: 1 }, + { label: '否', value: 0 }, + ], + }, + }, + { + field: 'formType', + label: '类型', + component: 'ApiRadioGroup', + defaultValue: 0, + componentProps: { + options: [ + { label: '常规表单', value: 0 }, + { label: '视图表单', value: 1 }, + { label: '自动建表', value: 2 }, + ], + }, + colProps: { lg: 24, md: 24 }, + dynamicDisabled: ({ values }) => { + return values.id; + }, + }, + { + field: 'description', + component: 'InputTextArea', + label: '描述', + colProps: { + span: 24, + }, + defaultValue: '', + componentProps: { + placeholder: '请输入', + }, + }, + { + field: 'createUserName', + component: 'Input', + label: '创建人', + ifShow: false, + }, + { + field: 'createDate', + component: 'Input', + label: '创建时间', + ifShow: false, + }, + { + field: 'field1', + label: '', + colProps: { + span: 24, + }, + slot: 'addDatabaseTableSlot', + ifShow: ({ values }) => isButton(values.formType), + }, + { + field: 'field1', + label: '', + colProps: { + span: 24, + }, + slot: 'addDatabaseContantSlot', + ifShow: ({ values }) => isButton(values.formType), + }, + { + field: 'field1', + label: '', + colProps: { + span: 24, + }, + slot: 'addViewsDatabaseTableSlot', + ifShow: ({ values }) => isButton2(values.formType), + }, +]; + +export const formSqlSchema: FormSchema[] = [ + { + field: 'name', + component: 'Input', + label: '名称', + colProps: { + span: 24, + }, + defaultValue: '', + required: true, + componentProps: { + placeholder: '请输入', + }, + }, + { + field: 'sql', + component: 'InputTextArea', + label: 'SQL', + colProps: { + span: 24, + }, + defaultValue: '', + required: true, + componentProps: { + placeholder: '@param 与主表关联参数值,比如 where id = @param;', + }, + }, +]; diff --git a/src/views/demo/onlineform/formdesign/form/index.vue b/src/views/demo/onlineform/formdesign/form/index.vue new file mode 100644 index 0000000..0035dd2 --- /dev/null +++ b/src/views/demo/onlineform/formdesign/form/index.vue @@ -0,0 +1,776 @@ + + + diff --git a/src/views/demo/onlineform/formdesign/form/sqlModal.vue b/src/views/demo/onlineform/formdesign/form/sqlModal.vue new file mode 100644 index 0000000..0982180 --- /dev/null +++ b/src/views/demo/onlineform/formdesign/form/sqlModal.vue @@ -0,0 +1,80 @@ + + + diff --git a/src/views/demo/onlineform/formdesign/formScheme.data.ts b/src/views/demo/onlineform/formdesign/formScheme.data.ts new file mode 100644 index 0000000..4d19d0b --- /dev/null +++ b/src/views/demo/onlineform/formdesign/formScheme.data.ts @@ -0,0 +1,223 @@ +import { BasicColumn, FormSchema } from '@/components/Table'; +import { h } from 'vue'; +import { Tag, Switch } from 'ant-design-vue'; +import { functionUpdateState } from '@/api/demo/formScheme'; +import { useMessage } from '@/hooks/web/useMessage'; + +type CheckedType = boolean | string | number; + +export const columns: BasicColumn[] = [ + { + title: '名称', + dataIndex: 'name', + width: 120, + }, + { + title: '分类', + dataIndex: 'category', + width: 80, + }, + { + title: '类型', + dataIndex: 'formType', + width: 80, + customRender: ({ record }) => { + let color = ''; + let text = ''; + const formType = record.formType; + if (formType === 0) { + color = 'green'; + text = '常规表单'; + } else if (formType === 1) { + color = 'yellow'; + text = '视图表单'; + } else if (formType === 2) { + color = 'blue'; + text = '自动建表'; + } + return h(Tag, { color: color }, () => text); + }, + }, + { + title: '状态', + dataIndex: 'enabledMark', + width: 80, + customRender: ({ record }) => { + if (!record.type || record.type === 2) { + const color = 'blue'; + const text = '草稿'; + return h(Tag, { color: color }, () => text); + } else { + return h(Switch, { + checked: record.enabledMark === 1, + checkedChildren: '启用', + unCheckedChildren: '停用', + loading: record.pendingStatus, + onChange(checked: CheckedType) { + record.pendingStatus = true; + const newStatus = checked ? 1 : 0; + const { createMessage } = useMessage(); + functionUpdateState({ id: record.id, state: newStatus }) + .then(() => { + record.enabledMark = newStatus; + createMessage.success(`已成功修改表单状态`); + }) + .catch(() => { + createMessage.error('修改表单状态失败'); + }) + .finally(() => { + record.pendingStatus = false; + }); + }, + }); + } + }, + }, + { + title: '创建人', + dataIndex: 'createUserName', + width: 80, + }, + { + title: '创建时间', + dataIndex: 'createDate', + width: 120, + }, +]; + +const colProps = { + span: 24, +}; + +export const searchFormSchema: FormSchema[] = [ + { + field: 'keyWord', + label: '名称', + component: 'Input', + colProps: { span: 8 }, + }, +]; + +export const formSchema: FormSchema[] = [ + { + field: 'itemDetailId', + component: 'Input', + ifShow: false, + }, + { + field: 'itemId', + label: '项目ID', + component: 'Input', + ifShow: false, + }, + { + field: 'parentId', + label: '上级', + component: 'TreeSelect', + componentProps: { + fieldNames: { + label: 'itemName', + key: 'itemId', + value: 'itemValue', + }, + getPopupContainer: () => document.body, + }, + colProps, + }, + { + field: 'itemCode', + component: 'Input', + ifShow: false, + }, + { + field: 'itemName', + label: '项目名', + component: 'Input', + required: true, + colProps, + }, + { + field: 'itemValue', + label: '项目值', + component: 'Input', + required: true, + colProps, + }, + { + field: 'quickQuery', + component: 'Input', + ifShow: false, + }, + { + field: 'simpleSpelling', + component: 'Input', + ifShow: false, + }, + { + field: 'isDefault', + component: 'Input', + ifShow: false, + }, + { + field: 'sortCode', + label: '排序', + component: 'InputNumber', + required: true, + colProps, + }, + { + field: 'deleteMark', + component: 'Input', + ifShow: false, + }, + { + field: 'enabledMark', + label: '状态', + component: 'Switch', + colProps, + ifShow: false, + render: (scope) => { + return h('Switch', { + props: { + value: scope.model?.enabledMark === 1, + }, + }); + }, + }, + { + field: 'description', + label: '备注', + component: 'InputTextArea', + colProps, + }, + { + field: 'createDate', + component: 'Input', + ifShow: false, + }, + { + field: 'createUserId', + component: 'Input', + ifShow: false, + }, + { + field: 'createUserName', + component: 'Input', + ifShow: false, + }, + { + field: 'modifyDate', + component: 'Input', + ifShow: false, + }, + { + field: 'modifyUserId', + component: 'Input', + ifShow: false, + }, + { + field: 'modifyUserName', + component: 'Input', + ifShow: false, + }, +]; diff --git a/src/views/demo/onlineform/formdesign/index.vue b/src/views/demo/onlineform/formdesign/index.vue new file mode 100644 index 0000000..32ff42d --- /dev/null +++ b/src/views/demo/onlineform/formdesign/index.vue @@ -0,0 +1,298 @@ + + diff --git a/src/views/demo/onlineform/formdesign/modal/AutomaticModal.vue b/src/views/demo/onlineform/formdesign/modal/AutomaticModal.vue new file mode 100644 index 0000000..6a6e71b --- /dev/null +++ b/src/views/demo/onlineform/formdesign/modal/AutomaticModal.vue @@ -0,0 +1,1108 @@ + + diff --git a/src/views/demo/onlineform/formdesign/modal/HistoryModal.vue b/src/views/demo/onlineform/formdesign/modal/HistoryModal.vue new file mode 100644 index 0000000..483a5ae --- /dev/null +++ b/src/views/demo/onlineform/formdesign/modal/HistoryModal.vue @@ -0,0 +1,131 @@ + + diff --git a/src/views/demo/onlineform/formdesign/modal/PreviewModal.vue b/src/views/demo/onlineform/formdesign/modal/PreviewModal.vue new file mode 100644 index 0000000..a69c2f0 --- /dev/null +++ b/src/views/demo/onlineform/formdesign/modal/PreviewModal.vue @@ -0,0 +1,17 @@ + + diff --git a/src/views/demo/onlineform/formdesign/modal/modelData.ts b/src/views/demo/onlineform/formdesign/modal/modelData.ts new file mode 100644 index 0000000..afab7cd --- /dev/null +++ b/src/views/demo/onlineform/formdesign/modal/modelData.ts @@ -0,0 +1,138 @@ +import { BasicColumn } from '@/components/Table'; +import { h } from 'vue'; +import { Tag } from 'ant-design-vue'; + +export function getHistoryColumns(): BasicColumn[] { + return [ + { + title: 'id', + dataIndex: 'id', + ifShow: false, + }, + { + title: 'schemeInfoId', + dataIndex: 'schemeInfoId', + ifShow: false, + }, + { + title: 'scheme', + dataIndex: 'scheme', + ifShow: false, + }, + { + title: 'createUserId', + dataIndex: 'createUserId', + ifShow: false, + }, + { + title: '创建人', + width: 150, + dataIndex: 'createUserName', + }, + { + title: '创建时间', + width: 150, + dataIndex: 'createDate', + }, + { + title: 'tenantId', + dataIndex: 'tenantId', + ifShow: false, + }, + { + title: '状态', + dataIndex: 'type', + width: 80, + customRender: ({ record }) => { + if (!record.type || record.type === 2) { + const color = 'gray'; + const text = '草稿'; + return h(Tag, { color: color }, () => text); + } else { + const color = 'green'; + const text = '正式'; + return h(Tag, { color: color }, () => text); + } + }, + }, + { + title: '当前版本', + dataIndex: 'currentVersion', + width: 80, + }, + { + title: '操作', + dataIndex: 'action', + width: 80, + }, + ]; +} + +export const dbMainColumns: BasicColumn[] = [ + { + title: '类型', + dataIndex: 'type', + width: 50, + customRender: ({ record }) => { + const status = record.type; + let enable; + if (status == 'main') { + enable = true; + } else { + enable = false; + } + const color = enable ? '#67c23a' : '#e6a23c'; + const text = enable ? '主表' : '子表'; + return h(Tag, { color: color }, () => text); + }, + }, + { + title: '表名', + dataIndex: 'tableName', + width: 150, + }, + { + title: '备注', + dataIndex: 'description', + width: 150, + }, +]; + +export const dbColumnInfoColumns: BasicColumn[] = [ + { + title: '字段名', + dataIndex: 'dbColumnName', + width: 150, + }, + { + title: '长度', + dataIndex: 'length', + width: 100, + }, + { + title: '数据格式(默认varchar)', + dataIndex: 'dataType', + width: 120, + }, + { + title: '备注', + dataIndex: 'columnDescription', + width: 120, + }, + { + dataIndex: 'isNullable', + ifShow: false, + }, + { + dataIndex: 'isIdentity', + ifShow: false, + }, + { + dataIndex: 'isPrimarykey', + ifShow: false, + }, + { + dataIndex: 'decimalDigits', + ifShow: false, + }, +]; diff --git a/src/views/demo/onlineform/util.ts b/src/views/demo/onlineform/util.ts new file mode 100644 index 0000000..79549b6 --- /dev/null +++ b/src/views/demo/onlineform/util.ts @@ -0,0 +1,101 @@ +export const cardNestStructure = (data) => { + let childList = {} + let result = [] + data.forEach(item => { + if(item.schemas){ + item.schemas = cardNestStructure(item.schemas) + result.push(item) + }else if(item.ptype){ + if(Object.keys(item).includes('children')){ + item.children = childList[item.field] || [] + } + if(item.component === 'CardGroup' && Object.keys(item).includes('componentProps')){ + item.componentProps.options = childList[item.field] || [] + } + let pushItem = {} + Object.keys(item).forEach(key => { + if(key !== 'ptype' && key !== 'pfield'){ + pushItem[key] = item[key] + } + }) + if(childList[item.pfield]){ + childList[item.pfield].push(pushItem) + }else{ + childList[item.pfield] = [pushItem] + } + + }else if(item.component === 'CardGroup'){ + item.componentProps.options = childList[item.field] || [] + result.push(item) + }else if(item.component === 'Card'){ + item.columns[0].children = childList[item.field] || [] + result.push(item) + }else if(item.field && item.field.indexOf('use_card') !== -1){ + item.children = childList[item.field] || [] + result.push(item) + }else{ + result.push(item) + } + }) + return result +} +export const changeCardStructure = (data) => { + let result = []; + if (data && data.length > 0) { + data.forEach((item) => { + if (item.component === 'Tabs') { + item.componentProps.options = changeCardStructure(item.componentProps.options); + } else if (item.component === 'CardGroup') { + item.componentProps.options = changeCardStructure(item.componentProps.options); + item.componentProps.options.forEach((childItem) => { + if (childItem.pfield) { + result.push(childItem); + } else { + result.push({ ...childItem, ptype: 'card', pfield: item.field }); + } + }); + item.componentProps.options = []; + } else if (item.component === 'Grid' && item.label === '栅格布局') { + item.columns = changeCardStructure(item.columns); + item.columns.forEach((childItem) => { + childItem.children.forEach((col) => { + result.push({ ...col, ptype: 'gridlayout', pfield: item.field }); + }); + }); + } else if (item.children && !item.field) { + item.children = changeCardStructure(item.children); + } else if (item.children && item.field.indexOf('use_card') === -1) { + item.children = changeCardStructure(item.children); + item.children = []; + } else { + if (['Card'].includes(item.component)) { + item.columns[0].children = changeCardStructure(item.columns[0].children); + if (item.component === 'Card' && item.columns[0].children) { + item.columns[0].children.forEach((childItem) => { + if (childItem.pfield) { + result.push(childItem); + } else { + result.push({ ...childItem, ptype: 'card', pfield: item.field }); + } + }); + item.columns[0].children = []; + } + } else if (item.field && item.field.indexOf('use_card') !== -1) { + item.children = changeCardStructure(item.children); + item.children.forEach((childItem) => { + if (childItem.pfield) { + result.push(childItem); + } else { + result.push({ ...childItem, ptype: 'card', pfield: item.field }); + } + }); + item.children = []; + } + } + result.push(item); + }); + return result; + } else { + return data; + } +}; \ No newline at end of file diff --git a/src/views/demo/page/result/fail/index.vue b/src/views/demo/page/result/fail/index.vue new file mode 100644 index 0000000..3e3e6e2 --- /dev/null +++ b/src/views/demo/page/result/fail/index.vue @@ -0,0 +1,47 @@ + + + diff --git a/src/views/demo/page/result/success/index.vue b/src/views/demo/page/result/success/index.vue new file mode 100644 index 0000000..ec80e02 --- /dev/null +++ b/src/views/demo/page/result/success/index.vue @@ -0,0 +1,51 @@ + + + diff --git a/src/views/demo/permission/CurrentPermissionMode.vue b/src/views/demo/permission/CurrentPermissionMode.vue new file mode 100644 index 0000000..2209a74 --- /dev/null +++ b/src/views/demo/permission/CurrentPermissionMode.vue @@ -0,0 +1,23 @@ + + diff --git a/src/views/demo/permission/back/Btn.vue b/src/views/demo/permission/back/Btn.vue new file mode 100644 index 0000000..1596555 --- /dev/null +++ b/src/views/demo/permission/back/Btn.vue @@ -0,0 +1,96 @@ + + + diff --git a/src/views/demo/permission/back/index.vue b/src/views/demo/permission/back/index.vue new file mode 100644 index 0000000..25fb98d --- /dev/null +++ b/src/views/demo/permission/back/index.vue @@ -0,0 +1,58 @@ + + + diff --git a/src/views/demo/permission/front/AuthPageA.vue b/src/views/demo/permission/front/AuthPageA.vue new file mode 100644 index 0000000..cdc08a5 --- /dev/null +++ b/src/views/demo/permission/front/AuthPageA.vue @@ -0,0 +1,16 @@ + + + diff --git a/src/views/demo/permission/front/AuthPageB.vue b/src/views/demo/permission/front/AuthPageB.vue new file mode 100644 index 0000000..f6c5dda --- /dev/null +++ b/src/views/demo/permission/front/AuthPageB.vue @@ -0,0 +1,16 @@ + + + diff --git a/src/views/demo/permission/front/Btn.vue b/src/views/demo/permission/front/Btn.vue new file mode 100644 index 0000000..0d1b182 --- /dev/null +++ b/src/views/demo/permission/front/Btn.vue @@ -0,0 +1,82 @@ + + + diff --git a/src/views/demo/permission/front/index.vue b/src/views/demo/permission/front/index.vue new file mode 100644 index 0000000..3353797 --- /dev/null +++ b/src/views/demo/permission/front/index.vue @@ -0,0 +1,47 @@ + + + diff --git a/src/views/demo/system/account/AccountDetail.vue b/src/views/demo/system/account/AccountDetail.vue new file mode 100644 index 0000000..65b0131 --- /dev/null +++ b/src/views/demo/system/account/AccountDetail.vue @@ -0,0 +1,61 @@ + + + + + diff --git a/src/views/demo/system/account/AccountModal.vue b/src/views/demo/system/account/AccountModal.vue new file mode 100644 index 0000000..11f324d --- /dev/null +++ b/src/views/demo/system/account/AccountModal.vue @@ -0,0 +1,89 @@ + + diff --git a/src/views/demo/system/account/AssignRoleModal.vue b/src/views/demo/system/account/AssignRoleModal.vue new file mode 100644 index 0000000..0a07372 --- /dev/null +++ b/src/views/demo/system/account/AssignRoleModal.vue @@ -0,0 +1,110 @@ + + diff --git a/src/views/demo/system/account/DeptTree.vue b/src/views/demo/system/account/DeptTree.vue new file mode 100644 index 0000000..879abf2 --- /dev/null +++ b/src/views/demo/system/account/DeptTree.vue @@ -0,0 +1,102 @@ + + diff --git a/src/views/demo/system/account/OrgPositonModal.vue b/src/views/demo/system/account/OrgPositonModal.vue new file mode 100644 index 0000000..00d1873 --- /dev/null +++ b/src/views/demo/system/account/OrgPositonModal.vue @@ -0,0 +1,273 @@ + + + diff --git a/src/views/demo/system/account/account.data.ts b/src/views/demo/system/account/account.data.ts new file mode 100644 index 0000000..6fd3516 --- /dev/null +++ b/src/views/demo/system/account/account.data.ts @@ -0,0 +1,125 @@ +import { BasicColumn, FormSchema } from '@/components/Table'; + +/** + * transform mock data + * { + * 0: '华东分部', + * '0-0': '华东分部-研发部' + * '0-1': '华东分部-市场部', + * ... + * } + */ +export const deptMap = (() => { + const pDept = ['华东分部', '华南分部', '西北分部']; + const cDept = ['研发部', '市场部', '商务部', '财务部']; + + return pDept.reduce((map, p, pIdx) => { + map[pIdx] = p; + + cDept.forEach((c, cIndex) => (map[`${pIdx}-${cIndex}`] = `${p}-${c}`)); + + return map; + }, {}); +})(); + +export const columns: BasicColumn[] = [ + { + title: '账号', + dataIndex: 'account', + width: 120, + }, + { + title: '姓名', + dataIndex: 'name', + width: 120, + }, + { + title: '所属部门', + dataIndex: 'department', + }, + { + title: '角色', + dataIndex: 'role', + }, + { + title: '创建时间', + dataIndex: 'createtime', + width: 180, + }, +]; + +export const searchFormSchema: FormSchema[] = [ + { + field: 'key', + label: '关键字', + component: 'Input', + colProps: { span: 8 }, + }, +]; + +export const accountFormSchema: FormSchema[] = [ + { + field: 'id', + label: '姓名', + component: 'Input', + required: true, + ifShow: false, + }, + { + field: 'account', + label: '账号', + component: 'Input', + // helpMessage: ['本字段演示异步验证', '不能输入带有admin的账号'], + rules: [ + { + required: true, + message: '请输入账号', + }, + // { + // trigger: 'blur', + // validator(_, value) { + // return new Promise((resolve, reject) => { + // if (!value) return resolve(); + // isAccountExist(value) + // .then(resolve) + // .catch((err) => { + // reject(err.message || '验证失败'); + // }); + // }); + // }, + // }, + ], + }, + { + field: 'name', + label: '姓名', + component: 'Input', + required: true, + }, + { + field: 'password', + label: '密码', + component: 'InputPassword', + }, + { + field: 'status', + label: '状态', + component: 'RadioButtonGroup', + defaultValue: 0, + componentProps: { + options: [ + { label: '启用', value: 0 }, + { label: '停用', value: 1 }, + ], + }, + }, + { + field: 'field13', + component: 'CropperAvatar', + label: '头像上传', + colProps: { + span: 8, + }, + slot: 'avatar', + }, +]; diff --git a/src/views/demo/system/account/index.vue b/src/views/demo/system/account/index.vue new file mode 100644 index 0000000..307e5dd --- /dev/null +++ b/src/views/demo/system/account/index.vue @@ -0,0 +1,148 @@ + + +./page.ts diff --git a/src/views/demo/system/account/page.ts b/src/views/demo/system/account/page.ts new file mode 100644 index 0000000..00975f0 --- /dev/null +++ b/src/views/demo/system/account/page.ts @@ -0,0 +1,7 @@ + +export { default as DeptTree } from './DeptTree.vue'; +export { default as AccountDetail } from './AccountDetail.vue'; +export { default as AccountModal } from './AccountModal.vue'; +export { default as OrgPositonModal } from './OrgPositonModal.vue'; +export { default as AssignRoleModal } from './AssignRoleModal.vue'; + diff --git a/src/views/demo/system/casemodification/HistoryModal/ShowDetail/index.vue b/src/views/demo/system/casemodification/HistoryModal/ShowDetail/index.vue new file mode 100644 index 0000000..ecdb81e --- /dev/null +++ b/src/views/demo/system/casemodification/HistoryModal/ShowDetail/index.vue @@ -0,0 +1,33 @@ + + + + + diff --git a/src/views/demo/system/casemodification/HistoryModal/index.vue b/src/views/demo/system/casemodification/HistoryModal/index.vue new file mode 100644 index 0000000..ce8dbe7 --- /dev/null +++ b/src/views/demo/system/casemodification/HistoryModal/index.vue @@ -0,0 +1,71 @@ + + + + + diff --git a/src/views/demo/system/casemodification/HistoryModal/util.ts b/src/views/demo/system/casemodification/HistoryModal/util.ts new file mode 100644 index 0000000..f6a121f --- /dev/null +++ b/src/views/demo/system/casemodification/HistoryModal/util.ts @@ -0,0 +1,42 @@ +export const columns = [ + { + title: '修改时间', + dataIndex: 'recordingtime', + key: 'recordingtime', + }, + { + title: '面积', + dataIndex: 'area', + key: 'area', + }, + { + title: '农用地面积', + dataIndex: 'nongyongdi_area', + key: 'nongyongdi_area', + }, + { + title: '耕地面积', + dataIndex: 'gengdi_area', + key: 'gengdi_area', + }, + { + title: '永农面积', + dataIndex: 'yongjiujibennongtian_area', + key: 'yongjiujibennongtian_area', + }, + { + title: '重点区域面积', + dataIndex: 'zhongdianquyu_area', + key: 'zhongdianquyu_area', + }, + { + title: '生态保护红线面积', + dataIndex: 'shengtaibaohuhongxian_area', + key: 'shengtaibaohuhongxian_area', + }, + { + title: '国土空间规划面积', + dataIndex: 'guotukongjianguihua_area', + key: 'guotukongjianguihua_area', + } +] \ No newline at end of file diff --git a/src/views/demo/system/casemodification/InfoModal/index.vue b/src/views/demo/system/casemodification/InfoModal/index.vue new file mode 100644 index 0000000..5208826 --- /dev/null +++ b/src/views/demo/system/casemodification/InfoModal/index.vue @@ -0,0 +1,217 @@ + + + + diff --git a/src/views/demo/system/casemodification/casemodification.data.ts b/src/views/demo/system/casemodification/casemodification.data.ts new file mode 100644 index 0000000..9c4f0c4 --- /dev/null +++ b/src/views/demo/system/casemodification/casemodification.data.ts @@ -0,0 +1,228 @@ +import { BasicColumn, FormSchema } from '@/components/Table'; +// import { getChildrenTree } from '@/api/demo/system'; + +const getYearList = () => { + const num = 10; + const currentYear = new Date().getFullYear(); + // 存储年份数据的数组 + const list: any = []; + // 获取当前年份 + // year.value = Number(`${currentYear}`); + list.push({ + value: Number(`${currentYear}`), + label: Number(`${currentYear}`), + }); + // 获取后面几年的数据 + for (let i = 1; i <= num; i++) { + list.push({ + value: Number(`${currentYear - i}`), + label: Number(`${currentYear - i}`), + }); + } + return list; +}; +export const columns: BasicColumn[] = [ + { + title: '图斑编号', + dataIndex: 'case_no', + width:180, + }, + { + title: '图斑描述', + dataIndex: 'case_description', + width:230, + }, + { + title: '区县', + dataIndex: 'countyname', + }, + { + title: '乡镇', + dataIndex: 'streetname', + }, + { + title: '社区', + dataIndex: 'communityname', + }, + { + title: '图斑面积', + dataIndex: 'area', + }, + { + title: '农用地面积', + dataIndex: 'nongyongdi_area', + }, + { + title: '耕地面积', + dataIndex: 'gengdi_area', + }, + { + title: '永农面积', + dataIndex: 'yongjiujibennongtian_area', + }, + { + title: '重点区域面积', + dataIndex: 'zhongdianquyu_area', + }, + { + title: '生态保护红线面积', + dataIndex: 'shengtaibaohuhongxian_area', + }, + { + title: '国土空间规划面积', + dataIndex: 'guotukongjianguihua_area', + }, +]; + +export const searchFormSchema: FormSchema[] = [ + // { + // field: 'year', + // component: 'Select', + // colProps: { span: 4 }, + // label: '年份', + // componentProps: { + // options: getYearList(), + // }, + // }, + // { + // field: 'tubanlaiyuan', + // label: '图斑来源', + // component: 'Select', + // colProps: { span: 4 }, + // componentProps: { + // options: [ + // { + // label: '全域巡查', + // value: '全域巡查', + // }, + // { + // label: '卫片下发', + // value: '卫片下发', + // }, + // ], + // }, + // }, + // { + // field: 'picihao', + // label: '批次', + // component: 'Select', + // colProps: { span: 4 }, + // componentProps: { + // options: [], + // }, + // }, + // { + // field: 'typename', + // label: '图斑类型', + // component: 'Select', + // colProps: { span: 4 }, + // componentProps: { + // options: [ + // { label: '农用地', value: '农用地' }, + // { label: '建设用地', value: '建设用地' }, + // { label: '推堆土', value: '推堆土' }, + // ], + // }, + // }, + // { + // field: 'isBuildName', + // label: '标注类型', + // component: 'Select', + // colProps: { span: 4 }, + // componentProps: { + // options: [ + // { label: '在建', value: '在建' }, + // { label: '已建成', value: '已建成' }, + // { label: '持续变化', value: '持续变化' }, + // ], + // }, + // }, + // { + // field: 'isIllegal', + // label: '判定结果', + // component: 'Select', + // colProps: { span: 4 }, + // componentProps: { + // options: [ + // { label: '合法', value: 0 }, + // { label: '违法', value: 1 }, + // { label: '其他', value: 2 }, + // ], + // }, + // }, + // { + // field: 'nowStatus', + // label: '当前状态', + // component: 'Select', + // componentProps: { + // options: [ + // { label: '待接收', value: '待接收' }, + // { label: '待填报', value: '待填报' }, + // { label: '待整改', value: '待整改' }, + // { label: '市级审核', value: '市级审核' }, + // { label: '县级审核', value: '县级审核' }, + // { label: '已归档', value: '已归档' }, + // ], + // }, + // colProps: { span: 4 }, + // }, + // { + // field: 'measureName', + // label: '整改措施', + // component: 'Select', + // colProps: { span: 4 }, + // componentProps: { + // options: [ + // { label: '拆除复耕', value: '0' }, + // { label: '补办手续', value: '1' }, + // ], + // }, + // }, + // { + // field: 'countyid', + // label: '区县', + // component: 'ApiSelect', + // colProps: { span: 4 }, + // componentProps: ({ tableAction, formModel }) => { + // return { + // api: getChildrenTree, + // params: { parentId: 371300 }, + // // 接口参数 + // resultField: 'result', + // labelField: 'name', + // valueField: 'id', + // onChange: () => { + // formModel.streetid = ''; + // }, + // }; + // }, + // }, + // { + // field: 'streetid', + // label: '乡镇', + // component: 'ApiSelect', + // colProps: { span: 4 }, + // componentProps: ({ formModel }) => { + // return { + // api: formModel.countyid && getChildrenTree, + // params: { parentId: formModel.countyid }, + // // 接口参数 + // resultField: 'result', + // labelField: 'name', + // valueField: 'id', + // }; + // }, + // }, + { + field: 'key', + label: '图斑编号', + component: 'Input', + colProps: { span: 4 }, + }, + { + field: 'originalcaseno', + label: '标识号', + component: 'Input', + colProps: { span: 4 }, + }, +]; diff --git a/src/views/demo/system/casemodification/index.vue b/src/views/demo/system/casemodification/index.vue new file mode 100644 index 0000000..a7bdcf4 --- /dev/null +++ b/src/views/demo/system/casemodification/index.vue @@ -0,0 +1,118 @@ + + + diff --git a/src/views/demo/system/coverage/MenuDrawer.vue b/src/views/demo/system/coverage/MenuDrawer.vue new file mode 100644 index 0000000..031aba3 --- /dev/null +++ b/src/views/demo/system/coverage/MenuDrawer.vue @@ -0,0 +1,81 @@ + + \ No newline at end of file diff --git a/src/views/demo/system/coverage/MenuTree.vue b/src/views/demo/system/coverage/MenuTree.vue new file mode 100644 index 0000000..72fb904 --- /dev/null +++ b/src/views/demo/system/coverage/MenuTree.vue @@ -0,0 +1,110 @@ + + diff --git a/src/views/demo/system/coverage/index.vue b/src/views/demo/system/coverage/index.vue new file mode 100644 index 0000000..c71f4ad --- /dev/null +++ b/src/views/demo/system/coverage/index.vue @@ -0,0 +1,134 @@ + + \ No newline at end of file diff --git a/src/views/demo/system/coverage/menu.data.ts b/src/views/demo/system/coverage/menu.data.ts new file mode 100644 index 0000000..0e7026d --- /dev/null +++ b/src/views/demo/system/coverage/menu.data.ts @@ -0,0 +1,198 @@ +import { BasicColumn, FormSchema } from '@/components/Table'; +import { h } from 'vue'; +import { Tag } from 'ant-design-vue'; +import Icon from '@/components/Icon/Icon.vue'; + +export const columns: BasicColumn[] = [ + { + title: '按钮名称', + dataIndex: 'name', + }, + { + title: 'DOMID', + dataIndex: 'domId', + }, + { + title: '排序', + dataIndex: 'sort', + }, + +]; + +const isDir = (type: string) => type === '0'; +const isMenu = (type: string) => type === '1'; +const isButton = (type: string) => type === '2'; + +export const searchFormSchema: FormSchema[] = [ + { + field: 'key', + label: '关键字', + component: 'Input', + colProps: { span: 8 }, + }, +]; + +export const formSchema: FormSchema[] = [ + { + field: 'type', + label: '类型', + component: 'RadioButtonGroup', + defaultValue: '1', + componentProps: { + options: [ + // { label: '目录', value: '0' }, + { label: '菜单', value: '1' }, + { label: '按钮', value: '2' }, + ], + }, + colProps: { lg: 24, md: 24 }, + }, + { + field: 'id', + label: '名称', + component: 'Input', + ifShow:false + }, + { + field: 'name', + label: '名称', + component: 'Input', + required: true, + }, + + { + field: 'parentId', + label: '上级', + component: 'TreeSelect', + componentProps: { + fieldNames: { + label: 'name', + key: 'id', + value: 'id', + }, + getPopupContainer: () => document.body, + }, + ifShow: ({ values }) => !isButton(values.type), + }, + { + field: 'moduleId', + label: '菜单', + component: 'TreeSelect', + componentProps: { + fieldNames: { + label: 'name', + key: 'id', + value: 'id', + }, + getPopupContainer: () => document.body, + }, + ifShow: ({ values }) => isButton(values.type), + required: true, + }, + { + field: 'domId', + label: 'DMOID', + component: 'Input', + required: true, + ifShow: ({ values }) => isButton(values.type), + }, + { + field: 'sortNo', + label: '排序', + component: 'InputNumber', + ifShow: ({ values }) => !isButton(values.type), + }, + { + field: 'sort', + label: '排序', + component: 'InputNumber', + ifShow: ({ values }) => isButton(values.type), + }, + { + field: 'class', + helpMessage: ['参考参数值', 'success、warning、error'], + label: '样式', + component: 'Input', + ifShow: ({ values }) => isButton(values.type), + }, + { + field: 'iconName', + label: '图标', + component: 'IconPicker', + ifShow: ({ values }) => !isButton(values.type), + }, + + { + field: 'url', + label: '路由地址', + component: 'Input', + required: true, + ifShow: ({ values }) => !isButton(values.type), + }, + // { + // field: 'component', + // label: '组件路径', + // component: 'Input', + // ifShow: ({ values }) => isMenu(values.type), + // }, + { + field: 'code', + label: '权限标识', + component: 'Input', + ifShow: ({ values }) => !isButton(values.type), + }, + { + field: 'status', + label: '是否系统', + component: 'RadioButtonGroup', + defaultValue: 1, + componentProps: { + options: [ + { label: '是', value: 0 }, + { label: '否', value: 1 }, + ], + }, + ifShow: ({ values }) => !isButton(values.type), + }, + // { + // field: 'isExt', + // label: '是否外链', + // component: 'RadioButtonGroup', + // defaultValue: '0', + // componentProps: { + // options: [ + // { label: '否', value: '0' }, + // { label: '是', value: '1' }, + // ], + // }, + // ifShow: ({ values }) => !isButton(values.type), + // }, + + // { + // field: 'keepalive', + // label: '是否缓存', + // component: 'RadioButtonGroup', + // defaultValue: '0', + // componentProps: { + // options: [ + // { label: '否', value: '0' }, + // { label: '是', value: '1' }, + // ], + // }, + // ifShow: ({ values }) => isMenu(values.type), + // }, + + // { + // field: 'show', + // label: '是否显示', + // component: 'RadioButtonGroup', + // defaultValue: '0', + // componentProps: { + // options: [ + // { label: '是', value: '0' }, + // { label: '否', value: '1' }, + // ], + // }, + // ifShow: ({ values }) => !isButton(values.type), + // }, +]; diff --git a/src/views/demo/system/databasemanage/DataBaseModal.vue b/src/views/demo/system/databasemanage/DataBaseModal.vue new file mode 100644 index 0000000..aaf34f4 --- /dev/null +++ b/src/views/demo/system/databasemanage/DataBaseModal.vue @@ -0,0 +1,127 @@ + + diff --git a/src/views/demo/system/databasemanage/index.data.ts b/src/views/demo/system/databasemanage/index.data.ts new file mode 100644 index 0000000..09535e9 --- /dev/null +++ b/src/views/demo/system/databasemanage/index.data.ts @@ -0,0 +1,103 @@ +import { BasicColumn, FormSchema } from '@/components/Table'; +import { h } from 'vue'; +import { Tag } from 'ant-design-vue'; + +export const columns: BasicColumn[] = [ + { + title: '名称', + dataIndex: 'dbName', + }, + { + title: '编码', + dataIndex: 'dbAlias', + }, + { + title: '类型', + dataIndex: 'dbType', + }, + { + title: '数据库地址', + dataIndex: 'serverAddress', + }, +]; +export const searchFormSchema: FormSchema[] = [ + { + field: 'keyWord', + label: '名称', + component: 'Input', + colProps: { span: 8 }, + }, +]; + +export const formSchema: FormSchema[] = [ + { + field: 'dbAlias', + label: '编码', + component: 'Input', + required: true, + }, + { + field: 'dbName', + label: '名称', + component: 'Input', + required: true, + }, + { + field: 'dbType', + label: '类型', + component: 'Select', + componentProps: { + options: [ + { + label: 'MySql', + value: 'MySql', + }, + { + label: 'SqlServer', + value: 'SqlServer', + }, + { + label: 'Oracle', + value: 'Oracle', + }, + { + label: 'PostgreSQL', + value: 'PostgreSQL', + }, + { + label: '达梦', + value: 'Dameng', + }, + { + label: '人大金仓', + value: 'Kdbndp', + }, + ], + }, + }, + { + field: 'serverAddress', + label: '服务器地址', + component: 'Input', + required: true, + }, + { + field: 'dbConnection', + label: '连接串', + colProps: { + span: 24, + }, + rules: [ + { + required: true, + message: '请输入连接串', + }, + ], + slot: 'dbConnection', + }, + { + field: 'description', + label: '说明', + component: 'InputTextArea', + }, +]; diff --git a/src/views/demo/system/databasemanage/index.vue b/src/views/demo/system/databasemanage/index.vue new file mode 100644 index 0000000..c2aa7d9 --- /dev/null +++ b/src/views/demo/system/databasemanage/index.vue @@ -0,0 +1,114 @@ + + diff --git a/src/views/demo/system/dbsource/dbsource.data.ts b/src/views/demo/system/dbsource/dbsource.data.ts new file mode 100644 index 0000000..72aee02 --- /dev/null +++ b/src/views/demo/system/dbsource/dbsource.data.ts @@ -0,0 +1,234 @@ +import { BasicColumn, FormSchema } from '@/components/Table'; +import { getDataBaseCodeList } from '@/api/formdesign/index'; + +// 数据源table +export const dbsourcesColumns: BasicColumn[] = [ + { + title: 'ID', + dataIndex: 'id', + ifShow: false, + }, + { + title: '编码', + dataIndex: 'code', + width: 200, + }, + { + title: '名称', + dataIndex: 'name', + width: 200, + }, + { + title: '数据库', + dataIndex: 'dbId', + width: 80, + }, + { + title: '创建人', + dataIndex: 'createUserName', + width: 80, + }, + { + title: '创建时间', + dataIndex: 'createDate', + width: 80, + }, + { + title: '创建人id', + dataIndex: 'reateUserId', + ifShow: false, + }, + { + title: '备注', + dataIndex: 'description', + ifShow: false, + }, + { + title: 'ID', + dataIndex: 'id', + ifShow: false, + }, + { + title: 'modifyDate', + dataIndex: 'modifyDate', + ifShow: false, + }, + { + title: 'modifyUserId', + dataIndex: 'modifyUserId', + ifShow: false, + }, + { + title: 'modifyUserName', + dataIndex: 'modifyUserName', + ifShow: false, + }, + { + title: 'SQL', + dataIndex: 'sql', + ifShow: false, + }, +]; +// 数据源table-搜索 +export const searchFormSchema: FormSchema[] = [ + { + field: 'keyword', + label: '名称', + component: 'Input', + colProps: { span: 8 }, + }, +]; +// 数据源table-新增、编辑 +export const formSchema: FormSchema[] = [ + { + field: 'code', + component: 'Input', + label: '编号', + colProps: { + span: 24, + }, + defaultValue: '', + required: true, + componentProps: { + placeholder: '请输入', + }, + }, + { + field: 'name', + component: 'Input', + label: '名称', + colProps: { + span: 24, + }, + defaultValue: '', + required: true, + componentProps: { + placeholder: '请输入', + }, + }, + { + field: 'dbId', + component: 'ApiTreeSelect', + label: '数据库', + required: true, + colProps: { + span: 24, + }, + componentProps: { + api: () => + getDataBaseCodeList({}).then((data: Recordable) => { + return new Promise((resolve) => { + resolve(data); + }); + }), + labelField: 'text', + valueField: 'value', + async: true, + onChange: (e, v) => { + console.log('ApiTreeSelect====>:', e, v); + }, + onLoadData: ({ treeData, resolve, treeNode }) => { + setTimeout(() => { + const children: Recordable[] = []; + treeData.value.forEach((item) => { + if (item.id == treeNode.id) { + if (item.childNodes) { + item.childNodes.forEach((val) => { + children.push({ + text: val.text, + value: val.value, + }); + }); + } + } + }); + children.forEach((item) => { + item.isLeaf = false; + item.children = []; + }); + treeNode.dataRef.children = children; + treeData.value = [...treeData.value]; + resolve(); + return; + }, 300); + }, + }, + }, + { + field: 'sql', + component: 'InputTextArea', + label: 'SQL语句', + colProps: { + span: 24, + }, + defaultValue: '', + required: true, + componentProps: { + placeholder: '', + }, + }, + { + field: 'description', + component: 'InputTextArea', + label: '描述', + colProps: { + span: 24, + }, + defaultValue: '', + componentProps: { + placeholder: '请输入', + }, + }, + { + field: 'id', + component: 'Input', + label: 'id', + ifShow: false, + }, + { + field: 'createUserId', + component: 'Input', + label: '创建人', + ifShow: false, + }, + { + field: 'createUserName', + component: 'Input', + label: '创建人', + ifShow: false, + }, + { + field: 'createDate', + component: 'Input', + label: '创建时间', + ifShow: false, + }, + { + field: 'modifyUserId', + component: 'Input', + label: '修改人', + ifShow: false, + }, + { + field: 'modifyUserName', + component: 'Input', + label: '修改人', + ifShow: false, + }, + { + field: 'modifyDate', + component: 'Input', + label: '修改时间', + ifShow: false, + }, + { + field: 'isEdit', + component: 'Input', + ifShow: false, + }, + { + field: 'tenantId', + component: 'Input', + ifShow: false, + }, +]; diff --git a/src/views/demo/system/dbsource/drawer.vue b/src/views/demo/system/dbsource/drawer.vue new file mode 100644 index 0000000..b98c418 --- /dev/null +++ b/src/views/demo/system/dbsource/drawer.vue @@ -0,0 +1,94 @@ + + diff --git a/src/views/demo/system/dbsource/index.vue b/src/views/demo/system/dbsource/index.vue new file mode 100644 index 0000000..e473702 --- /dev/null +++ b/src/views/demo/system/dbsource/index.vue @@ -0,0 +1,137 @@ + + diff --git a/src/views/demo/system/dbsource/modal.vue b/src/views/demo/system/dbsource/modal.vue new file mode 100644 index 0000000..3424d14 --- /dev/null +++ b/src/views/demo/system/dbsource/modal.vue @@ -0,0 +1,116 @@ + + + + diff --git a/src/views/demo/system/dept/DeptModal.vue b/src/views/demo/system/dept/DeptModal.vue new file mode 100644 index 0000000..40f0b91 --- /dev/null +++ b/src/views/demo/system/dept/DeptModal.vue @@ -0,0 +1,81 @@ + + diff --git a/src/views/demo/system/dept/DeptTree.vue b/src/views/demo/system/dept/DeptTree.vue new file mode 100644 index 0000000..746f44c --- /dev/null +++ b/src/views/demo/system/dept/DeptTree.vue @@ -0,0 +1,110 @@ + + diff --git a/src/views/demo/system/dept/PosGroupModal.vue b/src/views/demo/system/dept/PosGroupModal.vue new file mode 100644 index 0000000..e9d11d7 --- /dev/null +++ b/src/views/demo/system/dept/PosGroupModal.vue @@ -0,0 +1,59 @@ + + \ No newline at end of file diff --git a/src/views/demo/system/dept/dept.data.ts b/src/views/demo/system/dept/dept.data.ts new file mode 100644 index 0000000..d311f53 --- /dev/null +++ b/src/views/demo/system/dept/dept.data.ts @@ -0,0 +1,119 @@ +import { BasicColumn, FormSchema } from '@/components/Table'; +import { h } from 'vue'; +import { Tag } from 'ant-design-vue'; +import { getPosGroupList } from '@/api/demo/system'; + +export const columns: BasicColumn[] = [ + { + title: '部门名称', + dataIndex: 'name', + }, + // { + // title: '排序', + // dataIndex: 'sortNo', + // width: 50, + // }, + { + title: '状态', + dataIndex: 'status', + width: 80, + customRender: ({ record }) => { + const status = record.status; + const enable = ~~status === 0; + const color = enable ? 'green' : 'red'; + const text = enable ? '启用' : '停用'; + return h(Tag, { color: color }, () => text); + }, + }, + { + title: '创建时间', + dataIndex: 'createTime', + width: 180, + }, + // { + // title: '备注', + // dataIndex: 'remark', + // }, +]; + +export const searchFormSchema: FormSchema[] = [ + { + field: 'key', + label: '关键字', + component: 'Input', + colProps: { span: 8 }, + }, +]; +export const formGroupSchema: FormSchema[] = [ + { + field: 'posGroupId', + component: 'ApiSelect', + label: '职级组', + required: true, + componentProps: ({ formActionType, formModel }) => { + return { + api: getPosGroupList, // 接口 + // 接口参数 + resultField: 'result', + labelField: 'name', + valueField: 'id', + }; + }, + }, +]; + +export const formSchema: FormSchema[] = [ + { + field: 'id', + label: '部门id', + component: 'Input', + ifShow: true, + }, + { + field: 'name', + label: '部门名称', + component: 'Input', + required: true, + }, + { + field: 'parentId', + label: '上级部门', + component: 'TreeSelect', + componentProps: { + fieldNames: { + label: 'name', + key: 'id', + value: 'id', + }, + onChange:(value)=>{ + console.log(value) + }, + getPopupContainer: () => document.body, + }, + // required: true, + }, + // { + // field: 'orderNo', + // label: '排序', + // component: 'InputNumber', + // required: true, + // }, + { + field: 'status', + label: '状态', + component: 'RadioButtonGroup', + defaultValue: 0, + componentProps: { + options: [ + { label: '启用', value: 0 }, + { label: '停用', value: 1 }, + ], + }, + required: true, + }, + // { + // label: '备注', + // field: 'remark', + // component: 'InputTextArea', + // }, +]; diff --git a/src/views/demo/system/dept/index.vue b/src/views/demo/system/dept/index.vue new file mode 100644 index 0000000..0f87e4e --- /dev/null +++ b/src/views/demo/system/dept/index.vue @@ -0,0 +1,138 @@ + + diff --git a/src/views/demo/system/dept/page.ts b/src/views/demo/system/dept/page.ts new file mode 100644 index 0000000..4dd7761 --- /dev/null +++ b/src/views/demo/system/dept/page.ts @@ -0,0 +1,5 @@ + +export { default as DeptTree } from './DeptTree.vue'; +export { default as DeptModal } from './DeptModal.vue'; +export { default as PosGroupModal } from './PosGroupModal.vue'; + diff --git a/src/views/demo/system/graphicaltable/index.data.ts b/src/views/demo/system/graphicaltable/index.data.ts new file mode 100644 index 0000000..4fff29e --- /dev/null +++ b/src/views/demo/system/graphicaltable/index.data.ts @@ -0,0 +1,34 @@ +import { BasicColumn, FormSchema } from '@/components/Table'; + +// 图形化建表table +export const graphicaltableColumns: BasicColumn[] = [ + { + title: '表名', + dataIndex: 'tableName', + width: 200, + }, + { + title: '类型', + dataIndex: 'type', + width: 200, + }, + { + title: '行数据', + dataIndex: 'columnJson', + ifShow: false, + }, + { + title: '创建人', + dataIndex: 'createUser', + width: 200, + }, +]; +// 图形化建表-搜索 +export const searchFormSchema: FormSchema[] = [ + { + field: 'keyword', + label: '名称', + component: 'Input', + colProps: { span: 8 }, + }, +]; diff --git a/src/views/demo/system/graphicaltable/index.vue b/src/views/demo/system/graphicaltable/index.vue new file mode 100644 index 0000000..1102f6b --- /dev/null +++ b/src/views/demo/system/graphicaltable/index.vue @@ -0,0 +1,112 @@ + + diff --git a/src/views/demo/system/graphicaltable/modal/index.vue b/src/views/demo/system/graphicaltable/modal/index.vue new file mode 100644 index 0000000..f51c1e3 --- /dev/null +++ b/src/views/demo/system/graphicaltable/modal/index.vue @@ -0,0 +1,387 @@ + + + diff --git a/src/views/demo/system/graphicaltable/modal/modal.data.ts b/src/views/demo/system/graphicaltable/modal/modal.data.ts new file mode 100644 index 0000000..5c24f57 --- /dev/null +++ b/src/views/demo/system/graphicaltable/modal/modal.data.ts @@ -0,0 +1,42 @@ +import { BasicColumn } from '@/components/Table'; + +export const columns: BasicColumn[] = [ + { + title: '字段名', + dataIndex: 'name', + key: 'name', + }, + { + title: '类型', + dataIndex: 'type', + key: 'type', + }, + { + title: '备注', + dataIndex: 'explanation', + key: 'explanation', + }, + { + title: '操作', + dataIndex: 'action', + key: 'action', + }, +]; + +export const columns_isDetail: BasicColumn[] = [ + { + title: '字段名', + dataIndex: 'name', + key: 'name', + }, + { + title: '类型', + dataIndex: 'type', + key: 'type', + }, + { + title: '备注', + dataIndex: 'explanation', + key: 'explanation', + }, +]; diff --git a/src/views/demo/system/layermanagement/components/VisitSource.vue b/src/views/demo/system/layermanagement/components/VisitSource.vue new file mode 100644 index 0000000..56a2e31 --- /dev/null +++ b/src/views/demo/system/layermanagement/components/VisitSource.vue @@ -0,0 +1,82 @@ + + diff --git a/src/views/demo/system/layermanagement/index.vue b/src/views/demo/system/layermanagement/index.vue new file mode 100644 index 0000000..bde1e00 --- /dev/null +++ b/src/views/demo/system/layermanagement/index.vue @@ -0,0 +1,107 @@ + + diff --git a/src/views/demo/system/mapconfig/index.vue b/src/views/demo/system/mapconfig/index.vue new file mode 100644 index 0000000..25d6e3c --- /dev/null +++ b/src/views/demo/system/mapconfig/index.vue @@ -0,0 +1,589 @@ + + + + + \ No newline at end of file diff --git a/src/views/demo/system/menu/MenuDrawer.vue b/src/views/demo/system/menu/MenuDrawer.vue new file mode 100644 index 0000000..fa35b5f --- /dev/null +++ b/src/views/demo/system/menu/MenuDrawer.vue @@ -0,0 +1,126 @@ + + diff --git a/src/views/demo/system/menu/MenuTree.vue b/src/views/demo/system/menu/MenuTree.vue new file mode 100644 index 0000000..8fa3ffc --- /dev/null +++ b/src/views/demo/system/menu/MenuTree.vue @@ -0,0 +1,121 @@ + + diff --git a/src/views/demo/system/menu/index.vue b/src/views/demo/system/menu/index.vue new file mode 100644 index 0000000..078176e --- /dev/null +++ b/src/views/demo/system/menu/index.vue @@ -0,0 +1,148 @@ + + diff --git a/src/views/demo/system/menu/menu.data.ts b/src/views/demo/system/menu/menu.data.ts new file mode 100644 index 0000000..f598a78 --- /dev/null +++ b/src/views/demo/system/menu/menu.data.ts @@ -0,0 +1,209 @@ +import { BasicColumn, FormSchema } from '@/components/Table'; +import { h } from 'vue'; +import { Tag } from 'ant-design-vue'; +import Icon from '@/components/Icon/Icon.vue'; + +export const columns: BasicColumn[] = [ + { + title: '按钮名称', + dataIndex: 'name', + }, + { + title: 'DOMID', + dataIndex: 'domId', + }, + { + title: '排序', + dataIndex: 'sort', + }, + { + title: '样式', + dataIndex: 'class', + }, + { + title: '状态', + dataIndex: 'enabledMark', + width: 80, + customRender: ({ record }) => { + const color = record.status == 1 ? 'blue' : 'red'; + const text = record.status == 1 ? '启用' : '停用'; + return h(Tag, { color: color }, () => text); + }, + }, +]; + +const isDir = (type: string) => type === '0'; +const isMenu = (type: string) => type === '1'; +const isButton = (type: string) => type === '2'; + +export const searchFormSchema: FormSchema[] = [ + { + field: 'key', + label: '关键字', + component: 'Input', + colProps: { span: 8 }, + }, +]; + +export const formSchema: FormSchema[] = [ + { + field: 'type', + label: '类型', + component: 'RadioButtonGroup', + defaultValue: '1', + componentProps: { + options: [ + // { label: '目录', value: '0' }, + { label: '菜单', value: '1' }, + { label: '按钮', value: '2' }, + ], + }, + colProps: { lg: 24, md: 24 }, + }, + { + field: 'id', + label: '名称', + component: 'Input', + ifShow: false, + }, + { + field: 'name', + label: '名称', + component: 'Input', + required: true, + }, + + { + field: 'parentId', + label: '上级', + component: 'TreeSelect', + componentProps: { + fieldNames: { + label: 'name', + key: 'id', + value: 'id', + }, + getPopupContainer: () => document.body, + }, + ifShow: ({ values }) => !isButton(values.type), + }, + { + field: 'moduleId', + label: '菜单', + component: 'TreeSelect', + componentProps: { + fieldNames: { + label: 'name', + key: 'id', + value: 'id', + }, + getPopupContainer: () => document.body, + }, + ifShow: ({ values }) => isButton(values.type), + required: true, + }, + { + field: 'domId', + label: 'DMOID', + component: 'Input', + required: true, + ifShow: ({ values }) => isButton(values.type), + }, + { + field: 'sortNo', + label: '排序', + component: 'InputNumber', + ifShow: ({ values }) => !isButton(values.type), + }, + { + field: 'sort', + label: '排序', + component: 'InputNumber', + ifShow: ({ values }) => isButton(values.type), + }, + { + field: 'class', + helpMessage: ['参考参数值', 'success、warning、error'], + label: '样式', + component: 'Input', + ifShow: ({ values }) => isButton(values.type), + }, + { + field: 'iconName', + label: '图标', + component: 'IconPicker', + ifShow: ({ values }) => !isButton(values.type), + }, + + { + field: 'url', + label: '路由地址', + component: 'Input', + ifShow: ({ values }) => !isButton(values.type), + }, + // { + // field: 'component', + // label: '组件路径', + // component: 'Input', + // ifShow: ({ values }) => isMenu(values.type), + // }, + { + field: 'code', + label: '权限标识', + component: 'Input', + ifShow: ({ values }) => !isButton(values.type), + }, + { + field: 'status', + label: '是否启用', + component: 'RadioButtonGroup', + defaultValue: 1, + componentProps: { + options: [ + { label: '否', value: 0 }, + { label: '是', value: 1 }, + ], + }, + }, + // { + // field: 'isExt', + // label: '是否外链', + // component: 'RadioButtonGroup', + // defaultValue: '0', + // componentProps: { + // options: [ + // { label: '否', value: '0' }, + // { label: '是', value: '1' }, + // ], + // }, + // ifShow: ({ values }) => !isButton(values.type), + // }, + + // { + // field: 'keepalive', + // label: '是否缓存', + // component: 'RadioButtonGroup', + // defaultValue: '0', + // componentProps: { + // options: [ + // { label: '否', value: '0' }, + // { label: '是', value: '1' }, + // ], + // }, + // ifShow: ({ values }) => isMenu(values.type), + // }, + + // { + // field: 'show', + // label: '是否显示', + // component: 'RadioButtonGroup', + // defaultValue: '0', + // componentProps: { + // options: [ + // { label: '是', value: '0' }, + // { label: '否', value: '1' }, + // ], + // }, + // ifShow: ({ values }) => !isButton(values.type), + // }, +]; diff --git a/src/views/demo/system/menu/page.ts b/src/views/demo/system/menu/page.ts new file mode 100644 index 0000000..7c7f003 --- /dev/null +++ b/src/views/demo/system/menu/page.ts @@ -0,0 +1,4 @@ + +export { default as MenuDrawer } from './MenuDrawer.vue'; +export { default as MenuTree } from './MenuTree.vue'; + diff --git a/src/views/demo/system/password/index.vue b/src/views/demo/system/password/index.vue new file mode 100644 index 0000000..d23ee14 --- /dev/null +++ b/src/views/demo/system/password/index.vue @@ -0,0 +1,40 @@ + + diff --git a/src/views/demo/system/password/pwd.data.ts b/src/views/demo/system/password/pwd.data.ts new file mode 100644 index 0000000..668a3d4 --- /dev/null +++ b/src/views/demo/system/password/pwd.data.ts @@ -0,0 +1,46 @@ +import { FormSchema } from '@/components/Form'; + +export const formSchema: FormSchema[] = [ + { + field: 'passwordOld', + label: '当前密码', + component: 'InputPassword', + required: true, + }, + { + field: 'passwordNew', + label: '新密码', + component: 'StrengthMeter', + componentProps: { + placeholder: '新密码', + }, + rules: [ + { + required: true, + message: '请输入新密码', + }, + ], + }, + { + field: 'confirmPassword', + label: '确认密码', + component: 'InputPassword', + + dynamicRules: ({ values }) => { + return [ + { + required: true, + validator: (_, value) => { + if (!value) { + return Promise.reject('密码不能为空'); + } + if (value !== values.passwordNew) { + return Promise.reject('两次输入的密码不一致!'); + } + return Promise.resolve(); + }, + }, + ]; + }, + }, +]; diff --git a/src/views/demo/system/permissionmanagement/data/MenuDrawer.vue b/src/views/demo/system/permissionmanagement/data/MenuDrawer.vue new file mode 100644 index 0000000..75d1a11 --- /dev/null +++ b/src/views/demo/system/permissionmanagement/data/MenuDrawer.vue @@ -0,0 +1,393 @@ + + + diff --git a/src/views/demo/system/permissionmanagement/data/index.data.ts b/src/views/demo/system/permissionmanagement/data/index.data.ts new file mode 100644 index 0000000..60bcc54 --- /dev/null +++ b/src/views/demo/system/permissionmanagement/data/index.data.ts @@ -0,0 +1,214 @@ +import { BasicColumn, FormSchema } from '@/components/Table'; +import { h } from 'vue'; +import { Tag } from 'ant-design-vue'; +import { getRoleListByPage } from '@/api/demo/system'; + +export const columns: BasicColumn[] = [ + { + title: '编码', + dataIndex: 'codeName', + width: 120, + }, + { + title: '名称', + dataIndex: 'name', + width: 100, + }, + { + title: '授权类型', + dataIndex: 'objectType', + width: 100, + customRender: ({ record }) => { + let color = ''; + let text = ''; + const formType = record.objectType; + if (formType == 2 || formType == '2') { + color = 'green'; + text = '角色'; + } + if (formType == 1 || formType == '1') { + color = 'yellow'; + text = '用户'; + } + if (formType == 3 || formType == '3') { + color = 'orange'; + text = '所有用户'; + } + return h(Tag, { color: color }, () => text); + }, + }, + { + title: '授权对象', + dataIndex: 'objectName', + width: 100, + }, + { + title: '类型', + dataIndex: 'type', + width: 100, + customRender: ({ record }) => { + let color = ''; + let text = ''; + const formType = record.type; + if (formType == 2 || formType == '2') { + color = 'green'; + text = '自定义表单'; + } + if (formType == 1 || formType == '1') { + color = 'yellow'; + text = '普通'; + } + return h(Tag, { color: color }, () => text); + }, + }, + { + title: '创建人', + dataIndex: 'createUserName', + width: 100, + }, + { + title: '创建时间', + dataIndex: 'createDate', + width: 120, + }, +]; + +const colProps = { + span: 24, +}; + +export const searchFormSchema: FormSchema[] = [ + { + field: 'key', + label: '关键字', + component: 'Input', + colProps: { span: 8 }, + componentProps: { + placeholder: '请输入名称/编号', + }, + }, +]; + +export const formSchema: FormSchema[] = [ + { + field: 'itemDetailId', + component: 'Input', + ifShow: false, + }, + { + field: 'itemId', + label: '项目ID', + component: 'Input', + ifShow: false, + }, + { + field: 'parentId', + label: '上级', + component: 'TreeSelect', + componentProps: { + fieldNames: { + label: 'itemName', + key: 'itemId', + value: 'itemValue', + }, + getPopupContainer: () => document.body, + }, + colProps, + }, + { + field: 'itemCode', + component: 'Input', + ifShow: false, + }, + { + field: 'itemName', + label: '项目名', + component: 'Input', + required: true, + colProps, + }, + { + field: 'itemValue', + label: '项目值', + component: 'Input', + required: true, + colProps, + }, + { + field: 'quickQuery', + component: 'Input', + ifShow: false, + }, + { + field: 'simpleSpelling', + component: 'Input', + ifShow: false, + }, + { + field: 'isDefault', + component: 'Input', + ifShow: false, + }, + { + field: 'sortCode', + label: '排序', + component: 'InputNumber', + required: true, + colProps, + }, + { + field: 'deleteMark', + component: 'Input', + ifShow: false, + }, + { + field: 'enabledMark', + label: '状态', + component: 'Switch', + colProps, + ifShow: false, + render: (scope) => { + return h('Switch', { + props: { + value: scope.model?.enabledMark === 1, + }, + }); + }, + }, + { + field: 'description', + label: '备注', + component: 'InputTextArea', + colProps, + }, + { + field: 'createDate', + component: 'Input', + ifShow: false, + }, + { + field: 'createUserId', + component: 'Input', + ifShow: false, + }, + { + field: 'createUserName', + component: 'Input', + ifShow: false, + }, + { + field: 'modifyDate', + component: 'Input', + ifShow: false, + }, + { + field: 'modifyUserId', + component: 'Input', + ifShow: false, + }, + { + field: 'modifyUserName', + component: 'Input', + ifShow: false, + }, +]; diff --git a/src/views/demo/system/permissionmanagement/data/index.vue b/src/views/demo/system/permissionmanagement/data/index.vue new file mode 100644 index 0000000..5471c55 --- /dev/null +++ b/src/views/demo/system/permissionmanagement/data/index.vue @@ -0,0 +1,128 @@ + + diff --git a/src/views/demo/system/permissionmanagement/data/page.ts b/src/views/demo/system/permissionmanagement/data/page.ts new file mode 100644 index 0000000..8c970a7 --- /dev/null +++ b/src/views/demo/system/permissionmanagement/data/page.ts @@ -0,0 +1 @@ +export { default as MenuDrawer } from './MenuDrawer.vue'; diff --git a/src/views/demo/system/position/PositionDrawer.vue b/src/views/demo/system/position/PositionDrawer.vue new file mode 100644 index 0000000..00c000c --- /dev/null +++ b/src/views/demo/system/position/PositionDrawer.vue @@ -0,0 +1,126 @@ + + diff --git a/src/views/demo/system/position/PositionTree.vue b/src/views/demo/system/position/PositionTree.vue new file mode 100644 index 0000000..cb73157 --- /dev/null +++ b/src/views/demo/system/position/PositionTree.vue @@ -0,0 +1,103 @@ + + diff --git a/src/views/demo/system/position/index.vue b/src/views/demo/system/position/index.vue new file mode 100644 index 0000000..3066123 --- /dev/null +++ b/src/views/demo/system/position/index.vue @@ -0,0 +1,132 @@ + + diff --git a/src/views/demo/system/position/page.ts b/src/views/demo/system/position/page.ts new file mode 100644 index 0000000..eed78d6 --- /dev/null +++ b/src/views/demo/system/position/page.ts @@ -0,0 +1,4 @@ + +export { default as PositionDrawer } from './PositionDrawer.vue'; +export { default as PositionTree } from './PositionTree.vue'; + diff --git a/src/views/demo/system/position/position.data.ts b/src/views/demo/system/position/position.data.ts new file mode 100644 index 0000000..254edf4 --- /dev/null +++ b/src/views/demo/system/position/position.data.ts @@ -0,0 +1,88 @@ +import { BasicColumn, FormSchema } from '@/components/Table'; +import { h } from 'vue'; +import { Tag } from 'ant-design-vue'; +import Icon from '@/components/Icon/Icon.vue'; +import { getDeptList, getPositionsTree } from '@/api/demo/system'; + +export const columns: BasicColumn[] = [ + { + title: '职级名称', + dataIndex: 'name', + }, +]; + +const isDir = (type: string) => type === '0'; +const isMenu = (type: string) => type === '1'; +const isButton = (type: string) => type === '2'; + +export const searchFormSchema: FormSchema[] = [ + // { + // field: 'key', + // label: '关键字', + // component: 'Input', + // colProps: { span: 8 }, + // }, +]; + +export const formSchema: FormSchema[] = [ + { + field: 'type', + label: '类型', + component: 'RadioButtonGroup', + defaultValue: '2', + componentProps: { + options: [ + // { label: '目录', value: '0' }, + // { label: '职级组', value: '1' }, + { label: '职级', value: '2' }, + ], + }, + colProps: { lg: 24, md: 24 }, + }, + { + field: 'id', + label: '名称', + component: 'Input', + required: true, + ifShow:false + }, + { + field: 'name', + label: '名称', + component: 'Input', + required: true, + }, + { + field: 'orgId', + label: '所属部门', + component: 'TreeSelect', + componentProps: { + fieldNames: { + label: 'name', + key: 'id', + value: 'id', + }, + getPopupContainer: () => document.body, + }, + required: true, + }, + { + field: 'parentId', + label: '上级', + component: 'TreeSelect', + componentProps: { + fieldNames: { + label: 'name', + key: 'id', + value: 'id', + }, + getPopupContainer: () => document.body, + }, + }, + { + field: 'remark', + label: '备注', + component: 'Input', + ifShow: ({ values }) => isButton(values.type), + }, +]; diff --git a/src/views/demo/system/role/AccountModal.vue b/src/views/demo/system/role/AccountModal.vue new file mode 100644 index 0000000..ae92eb8 --- /dev/null +++ b/src/views/demo/system/role/AccountModal.vue @@ -0,0 +1,60 @@ + + + diff --git a/src/views/demo/system/role/ModulesModal.vue b/src/views/demo/system/role/ModulesModal.vue new file mode 100644 index 0000000..79e3dc0 --- /dev/null +++ b/src/views/demo/system/role/ModulesModal.vue @@ -0,0 +1,173 @@ + + diff --git a/src/views/demo/system/role/RoleDrawer.vue b/src/views/demo/system/role/RoleDrawer.vue new file mode 100644 index 0000000..f0b57cd --- /dev/null +++ b/src/views/demo/system/role/RoleDrawer.vue @@ -0,0 +1,73 @@ + + diff --git a/src/views/demo/system/role/RoleModal.vue b/src/views/demo/system/role/RoleModal.vue new file mode 100644 index 0000000..80063a3 --- /dev/null +++ b/src/views/demo/system/role/RoleModal.vue @@ -0,0 +1,75 @@ + + diff --git a/src/views/demo/system/role/index.vue b/src/views/demo/system/role/index.vue new file mode 100644 index 0000000..9bf73fd --- /dev/null +++ b/src/views/demo/system/role/index.vue @@ -0,0 +1,162 @@ + + diff --git a/src/views/demo/system/role/page.ts b/src/views/demo/system/role/page.ts new file mode 100644 index 0000000..26aa161 --- /dev/null +++ b/src/views/demo/system/role/page.ts @@ -0,0 +1,6 @@ + +export { default as AccountModal } from './AccountModal.vue'; +export { default as ModulesModal } from './ModulesModal.vue'; +export { default as RoleDrawer } from './RoleDrawer.vue'; +export { default as RoleModal } from './RoleModal.vue'; + diff --git a/src/views/demo/system/role/role.data.ts b/src/views/demo/system/role/role.data.ts new file mode 100644 index 0000000..115d576 --- /dev/null +++ b/src/views/demo/system/role/role.data.ts @@ -0,0 +1,101 @@ +import { BasicColumn, FormSchema } from '@/components/Table'; +import { h } from 'vue'; +import { Switch,Tag } from 'ant-design-vue'; +import { setRoleStatus } from '@/api/demo/system'; +import { useMessage } from '@/hooks/web/useMessage'; + +type CheckedType = boolean | string | number; +export const columns: BasicColumn[] = [ + { + title: '角色名称', + dataIndex: 'name', + width: 200, + }, + // { + // title: '状态', + // dataIndex: 'status', + // width: 120, + // customRender: ({ record }) => { + // if (!Reflect.has(record, 'pendingStatus')) { + // record.pendingStatus = false; + // } + // return h(Switch, { + // checked: record.status === '1', + // checkedChildren: '停用', + // unCheckedChildren: '启用', + // loading: record.pendingStatus, + // onChange(checked: CheckedType) { + // record.pendingStatus = true; + // const newStatus = checked ? '1' : '0'; + // const { createMessage } = useMessage(); + // setRoleStatus(record.id, newStatus) + // .then(() => { + // record.status = newStatus; + // createMessage.success(`已成功修改角色状态`); + // }) + // .catch(() => { + // createMessage.error('修改角色状态失败'); + // }) + // .finally(() => { + // record.pendingStatus = false; + // }); + // }, + // }); + // }, + // }, + { + title: '状态', + dataIndex: 'status', + width: 80, + customRender: ({ record }) => { + const status = record.status; + const enable = ~~status === 0; + const color = enable ? 'green' : 'red'; + const text = enable ? '启用' : '停用'; + return h(Tag, { color: color }, () => text); + }, + }, + { + title: '创建时间', + dataIndex: 'createTime', + width: 180, + }, +]; + +export const searchFormSchema: FormSchema[] = [ + { + field: 'key', + label: '关键字', + component: 'Input', + colProps: { span: 8 }, + }, + +]; + +export const formSchema: FormSchema[] = [ + { + field: 'id', + label: '角色名称', + required: true, + component: 'Input', + ifShow:false, + }, + { + field: 'name', + label: '角色名称', + required: true, + component: 'Input', + }, + { + field: 'status', + label: '状态', + component: 'RadioButtonGroup', + defaultValue: 0, + componentProps: { + options: [ + { label: '启用', value: 0}, + { label: '停用', value: 1 }, + ], + }, + }, +]; diff --git a/src/views/demo/system/version/index.vue b/src/views/demo/system/version/index.vue new file mode 100644 index 0000000..81f29fc --- /dev/null +++ b/src/views/demo/system/version/index.vue @@ -0,0 +1,366 @@ + + + diff --git a/src/views/demo/system/vxe-account/index.vue b/src/views/demo/system/vxe-account/index.vue new file mode 100644 index 0000000..e061dee --- /dev/null +++ b/src/views/demo/system/vxe-account/index.vue @@ -0,0 +1,86 @@ + + + diff --git a/src/views/demo/system/vxe-account/vxeAccount.data.ts b/src/views/demo/system/vxe-account/vxeAccount.data.ts new file mode 100644 index 0000000..9053be9 --- /dev/null +++ b/src/views/demo/system/vxe-account/vxeAccount.data.ts @@ -0,0 +1,84 @@ +import { VxeFormItemProps, VxeGridPropTypes } from '@/components/VxeTable'; +import { deptMap } from '../account/account.data'; + +export const columns: VxeGridPropTypes.Columns = [ + { + title: '用户名', + field: 'account', + width: 120, + }, + { + title: '昵称', + field: 'nickname', + width: 120, + }, + { + title: '邮箱', + field: 'email', + width: 120, + }, + { + title: '创建时间', + field: 'createTime', + width: 180, + }, + { + title: '角色', + field: 'role', + width: 200, + }, + { + title: '所属部门', + field: 'dept', + slots: { + default: ({ row }) => { + return deptMap[row.dept]; + }, + }, + }, + { + title: '备注', + field: 'remark', + }, + { + width: 160, + title: '操作', + align: 'center', + slots: { default: 'action' }, + fixed: 'right', + }, +]; + +export const searchFormSchema: VxeFormItemProps[] = [ + { + field: 'account', + title: '用户名', + itemRender: { + name: 'AInput', + }, + span: 6, + }, + { + field: 'nickname', + title: '昵称', + itemRender: { + name: 'AInput', + }, + span: 6, + }, + { + span: 12, + align: 'right', + className: '!pr-0', + itemRender: { + name: 'AButtonGroup', + children: [ + { + props: { type: 'primary', content: '查询', htmlType: 'submit' }, + attrs: { class: 'mr-2' }, + }, + { props: { type: 'default', htmlType: 'reset', content: '重置' } }, + ], + }, + }, +]; diff --git a/src/views/demo/task/completed/index.vue b/src/views/demo/task/completed/index.vue new file mode 100644 index 0000000..8e2e2b7 --- /dev/null +++ b/src/views/demo/task/completed/index.vue @@ -0,0 +1,176 @@ + + + + diff --git a/src/views/demo/task/uncompleted/index.vue b/src/views/demo/task/uncompleted/index.vue new file mode 100644 index 0000000..57fbf30 --- /dev/null +++ b/src/views/demo/task/uncompleted/index.vue @@ -0,0 +1,199 @@ + + + + diff --git a/src/views/demo/technologicalprocess/UseModal/index.vue b/src/views/demo/technologicalprocess/UseModal/index.vue new file mode 100644 index 0000000..d6496ac --- /dev/null +++ b/src/views/demo/technologicalprocess/UseModal/index.vue @@ -0,0 +1,136 @@ + + + + + + diff --git a/src/views/demo/technologicalprocess/index.vue b/src/views/demo/technologicalprocess/index.vue new file mode 100644 index 0000000..ad3a5aa --- /dev/null +++ b/src/views/demo/technologicalprocess/index.vue @@ -0,0 +1,136 @@ + + + + + + diff --git a/src/views/demo/technologicalprocess/util.ts b/src/views/demo/technologicalprocess/util.ts new file mode 100644 index 0000000..076dbdd --- /dev/null +++ b/src/views/demo/technologicalprocess/util.ts @@ -0,0 +1,41 @@ +import { FormSchema } from '@/components/Table'; +export const searchFormSchema: FormSchema[] = [ + { + field: 'key', + label: '关键字', + component: 'Input', + colProps: { span: 8 }, + }, +]; +export const emptyAddForm = { + name:'', + sort:'', + status:0, +} +export const modalColumns = [ + { + title:'角色名称', + dataIndex:'name', + }, + { + title:'状态', + dataIndex:'status', + } +] +export const columns = [ + { + title: '流程名称', + dataIndex: 'name', + width: 200, + }, + { + title: '流程顺序', + dataIndex: 'sort', + width: 80, + }, + { + title: '状态', + dataIndex: 'status', + width: 180, + }, +] diff --git a/src/views/demo/util.ts b/src/views/demo/util.ts new file mode 100644 index 0000000..bb3ac6b --- /dev/null +++ b/src/views/demo/util.ts @@ -0,0 +1,57 @@ +import { useUserStore } from '@/store/modules/user' +const userStore = useUserStore() +export const showDrawBack = (item, showAll = false) => { + if(showAll){ + if(item.is_shijibohui > 0 || item.is_drawback == 1){ + return true + }else{ + return false + } + } + let level = userStore.getUserInfo.orgMaxLevel + if((level == '0' && item.is_shijibohui > 0) || (level != '0' && (item.is_shijibohui > 0 || item.is_drawback == 1))){ + return true + }else { + return false + } +} +export const drawBackSpan = (item, showAll = false) => { + let level = userStore.getUserInfo.orgMaxLevel + let title = '' + if(item.is_shijibohui){ + title = '市' + } + if(item.is_drawback && ((level != '0') || showAll)){ + if(title != ''){ + title = title + ',' + } + title = title + '县' + } + return `${title} 驳回` +} +export const illegalminingDrawBackSpan = (item, showAll = false) => { + let level = userStore.getUserInfo.orgMaxLevel + let title = '' + if(item.is_shijibohui > 0){ + title = `市 (${item.shijibohui_count})` + } + if(item.is_drawback && ((level != '0') || showAll)){ + if(title != ''){ + title = title + ',' + } + title = title + '县' + } + return `${title} 驳回` +} +export const SubjectKeyList = { + '0000002': 'Subject_XCSJ', //巡查审计 + '0000001': 'Subject_WFYD', // 违法用地 + '100001': 'Subject_FFCK', //非法采矿 + '违法用地(卫片)': 'Subject_WPWF', + '0000003': 'Subject_WPCK', //非法采矿(卫片) + '0000004': 'Subject_GDFLH', //耕地非粮化 + '0000005': 'Subject_ZDWT1', //重点问题I类 + '0000006': 'Subject_ZDWT2', //重点问题II类 + '0000007': 'Subject_STBHHXJG', //生态保护红线监管 + '0000008': 'Subject_STXF', //生态修复 +} \ No newline at end of file diff --git a/src/views/demo/workflow/create/index.ts b/src/views/demo/workflow/create/index.ts new file mode 100644 index 0000000..9450776 --- /dev/null +++ b/src/views/demo/workflow/create/index.ts @@ -0,0 +1 @@ +export { default as Preview } from './preview.vue'; diff --git a/src/views/demo/workflow/create/index.vue b/src/views/demo/workflow/create/index.vue new file mode 100644 index 0000000..405fd8b --- /dev/null +++ b/src/views/demo/workflow/create/index.vue @@ -0,0 +1,180 @@ + + + + diff --git a/src/views/demo/workflow/create/preview.vue b/src/views/demo/workflow/create/preview.vue new file mode 100644 index 0000000..59acac8 --- /dev/null +++ b/src/views/demo/workflow/create/preview.vue @@ -0,0 +1,475 @@ + + + + diff --git a/src/views/demo/workflow/flowcode.ts b/src/views/demo/workflow/flowcode.ts new file mode 100644 index 0000000..9229a37 --- /dev/null +++ b/src/views/demo/workflow/flowcode.ts @@ -0,0 +1,42 @@ +export const flowCode = [ + { + code: '0000001', + name: '违法用地', + }, + { + code: '0000004', + name: '耕地非粮化', + }, + { + code: '100001', + name: '非法采矿工作管理', + }, + { + code: '0000003', + name: '非法采矿卫片下发', + }, + { + code: '0000005', + name: '重点问题1类', + }, + { + code: '0000006', + name: '重点问题2类', + }, + { + code: '0000002', + name: '巡察审计', + }, + { + code: '0000007', + name: '生态保护红线监管', + }, + { + code: '0000008', + name: '生态修复', + }, +]; +export const flowCodeName = (code) => { + const item = flowCode.find((item) => item.code === code); + return item ? item.name : ''; +}; diff --git a/src/views/demo/workflow/h5/audit.vue b/src/views/demo/workflow/h5/audit.vue new file mode 100644 index 0000000..43b9c41 --- /dev/null +++ b/src/views/demo/workflow/h5/audit.vue @@ -0,0 +1,722 @@ + + + + diff --git a/src/views/demo/workflow/h5/create.vue b/src/views/demo/workflow/h5/create.vue new file mode 100644 index 0000000..f4f2f16 --- /dev/null +++ b/src/views/demo/workflow/h5/create.vue @@ -0,0 +1,283 @@ + + + + diff --git a/src/views/demo/workflow/h5/look.vue b/src/views/demo/workflow/h5/look.vue new file mode 100644 index 0000000..8d4daf2 --- /dev/null +++ b/src/views/demo/workflow/h5/look.vue @@ -0,0 +1,430 @@ + + + + diff --git a/src/views/demo/workflow/h5/scheme.vue b/src/views/demo/workflow/h5/scheme.vue new file mode 100644 index 0000000..e1d3cf8 --- /dev/null +++ b/src/views/demo/workflow/h5/scheme.vue @@ -0,0 +1,86 @@ + + + + diff --git a/src/views/demo/workflow/revocation/index.vue b/src/views/demo/workflow/revocation/index.vue new file mode 100644 index 0000000..3259c0a --- /dev/null +++ b/src/views/demo/workflow/revocation/index.vue @@ -0,0 +1,287 @@ + + + + + diff --git a/src/views/demo/workflow/scheme/HistoryDrawer.vue b/src/views/demo/workflow/scheme/HistoryDrawer.vue new file mode 100644 index 0000000..7031c51 --- /dev/null +++ b/src/views/demo/workflow/scheme/HistoryDrawer.vue @@ -0,0 +1,159 @@ + + + + diff --git a/src/views/demo/workflow/scheme/SchemeDrawer.vue b/src/views/demo/workflow/scheme/SchemeDrawer.vue new file mode 100644 index 0000000..22fcb83 --- /dev/null +++ b/src/views/demo/workflow/scheme/SchemeDrawer.vue @@ -0,0 +1,83 @@ + + \ No newline at end of file diff --git a/src/views/demo/workflow/scheme/SchemeTree.vue b/src/views/demo/workflow/scheme/SchemeTree.vue new file mode 100644 index 0000000..a2e8793 --- /dev/null +++ b/src/views/demo/workflow/scheme/SchemeTree.vue @@ -0,0 +1,163 @@ + + diff --git a/src/views/demo/workflow/scheme/index.vue b/src/views/demo/workflow/scheme/index.vue new file mode 100644 index 0000000..2f2cfac --- /dev/null +++ b/src/views/demo/workflow/scheme/index.vue @@ -0,0 +1,207 @@ + + + diff --git a/src/views/demo/workflow/scheme/page.ts b/src/views/demo/workflow/scheme/page.ts new file mode 100644 index 0000000..5ddf292 --- /dev/null +++ b/src/views/demo/workflow/scheme/page.ts @@ -0,0 +1,6 @@ + +export { default as HistoryDrawer } from './HistoryDrawer.vue'; +export { default as SchemeDrawer } from './SchemeDrawer.vue'; +export { default as SchemeTree } from './SchemeTree.vue'; +export { default as Preview } from './preview.vue'; + diff --git a/src/views/demo/workflow/scheme/preview.vue b/src/views/demo/workflow/scheme/preview.vue new file mode 100644 index 0000000..113be61 --- /dev/null +++ b/src/views/demo/workflow/scheme/preview.vue @@ -0,0 +1,96 @@ + + + + diff --git a/src/views/demo/workflow/scheme/scheme.data.ts b/src/views/demo/workflow/scheme/scheme.data.ts new file mode 100644 index 0000000..231dbfe --- /dev/null +++ b/src/views/demo/workflow/scheme/scheme.data.ts @@ -0,0 +1,122 @@ +import { BasicColumn, FormSchema } from '@/components/Table'; +import { h } from 'vue'; +import { Tag,Switch } from 'ant-design-vue'; +import Icon from '@/components/Icon/Icon.vue'; +import {updateState} from '@/api/sys/WFSchemeInfo' +import { useMessage } from '@/hooks/web/useMessage'; +const { createConfirm, createMessage } = useMessage(); +export const columns: BasicColumn[] = [ + { + title: '编号', + dataIndex: 'code', + }, + { + title: '名称', + dataIndex: 'name', + }, + { + title: '分类', + dataIndex: 'category', + }, + { + title: '状态', + dataIndex: 'enabledMark', + width: 80, + customRender: ({ record }) => { + if (record.type == 2) { + const color = 'blue'; + const text = '草稿'; + return h(Tag, { color: color }, () => text); + } else { + return h(Switch, { + checked: record.enabledMark === 1, + checkedChildren: '启用', + unCheckedChildren: '停用', + loading: record.pendingStatus, + onChange(checked) { + record.pendingStatus = true; + const newStatus = checked ? 1 : 0; + const { createMessage } = useMessage(); + updateState({ id: record.id, state: newStatus }) + .then((data) => { + record.enabledMark = newStatus; + createMessage.success('状态修改成功'); + }) + .catch((err) => { + createMessage.success('状态修改失败'); + }) + .finally(() => { + record.pendingStatus = false; + }); + }, + }); + } + }, + }, + { + title: '创建人', + dataIndex: 'createUserName', + }, + { + title: '创建时间', + dataIndex: 'createDate', + }, + +]; + +const isDir = (type: string) => type === '0'; +const isMenu = (type: string) => type === '1'; +const isButton = (type: string) => type === '2'; + +export const searchFormSchema: FormSchema[] = [ + { + field: 'key', + label: '关键字', + component: 'Input', + colProps: { span: 8 }, + }, +]; + +export const formSchema: FormSchema[] = [ + { + field: 'itemDetailId', + label: '名称', + component: 'Input', + ifShow:false + }, + { + field: 'itemName', + label: '名称', + component: 'Input', + required: true, + }, + { + field: 'itemValue', + label: '值', + component: 'Input', + required: true, + }, + { + field: 'sortCode', + label: '排序', + component: 'InputNumber', + }, + { + field: 'enabledMark', + label: '是否有效', + component: 'RadioButtonGroup', + defaultValue: 1, + componentProps: { + options: [ + { label: '是', value: 0 }, + { label: '否', value: 1 }, + ], + }, + }, + { + field: 'description', + label: '备注', + component: 'InputTextArea', + }, +]; + diff --git a/src/views/demo/workflow/scheme/util.ts b/src/views/demo/workflow/scheme/util.ts new file mode 100644 index 0000000..e6f7f27 --- /dev/null +++ b/src/views/demo/workflow/scheme/util.ts @@ -0,0 +1,137 @@ +export const getRFields = (dataList, rFieldList, fieldList) => { + dataList.forEach( + (element: { label?: string; field?: string; component: any; itemProps: any }) => { + if (['InputGuid'].includes(element.component)) { + rFieldList.push({ + label: element.label, + // value:element.prop + value: element.field, + }); + } else if ( + ![ + 'Divider', + 'Grid', + 'Card', + 'CreateUser', + 'CreateTime', + 'ModifyUser', + 'ModifyTime', + 'CardGroup', + ].includes(element.component) && + !element.itemProps.hidden + ) { + let obj: any = element; + obj.required = element.itemProps.required; + // obj.componentProps.disabled = false; + obj.disabled = true; + obj.ifShow = true; + obj.upShow = false; + obj.fieldName = element.componentProps.fieldName; + fieldList.push(obj); + } else if (['Grid'].includes(element.component) || element.type == 'subTable') { + console.log('gridtable'); + fieldList.push({ + field: `${element.field}_add`, + label: `${element.label || '表格'}-添加按钮`, + required: false, + disabled: true, + upShow: false, + ifShow: false, + type: 'grid', + }); + fieldList.push({ + field: `${element.field}_remove`, + label: `${element.label || '表格'}-删除按钮`, + required: false, + disabled: true, + upShow: false, + ifShow: false, + type: 'grid', + }); + + fieldList.push({ + field: `${element.field}_required`, + label: `${element.label || '表格'}-数据`, + required: element.itemProps.required, + disabled: false, + upShow: false, + ifShow: false, + type: 'gridrequired', + }); + element.columns.forEach((child) => { + child.children.forEach((t) => { + fieldList.push({ + gridprop: element.field, + field: t.field, + label: `${element.label || '表格'}-${t.label}`, + required: t.itemProps.required, + disabled: true, + upShow: false, + ifShow: true, + fieldName: t.componentProps.fieldName, + ...t, + }); + }); + }); + } else if (['Card'].includes(element.component)) { + console.log(3); + element.columns.forEach((child) => { + child.children.forEach((t) => { + fieldList.push({ + gridprop: element.field, + field: t.field, + required: t.itemProps.required, + disabled: true, + ifShow: true, + upShow: false, + fieldName: t.componentProps.fieldName, + ...t, + }); + }); + }); + } else if ( + ['CreateUser', 'CreateTime', 'ModifyUser', 'ModifyTime'].includes(element.component) && + element.display + ) { + let obj: any = element; + obj.upShow = false; + obj.required = element.itemProps.required; + // obj.componentProps.disabled = false; + obj.disabled = true; + obj.ifShow = true; + obj.fieldName = element.componentProps.fieldName; + fieldList.push(obj); + } else if (['CardGroup'].includes(element.component)) { + let obj: any = element; + obj.upShow = false; + obj.required = element.itemProps.required; + // obj.componentProps.disabled = false; + obj.disabled = true; + obj.ifShow = true; + obj.fieldName = element.componentProps.fieldName; + obj.label = `卡片组-${element.label}`; + fieldList.push(obj); + fieldList = cardComponentChild(element.componentProps.options, fieldList); + } + }, + ); + return { rFieldList, fieldList }; +}; +const cardComponentChild = (data, result) => { + data.forEach((optionsElement) => { + optionsElement.children.forEach((childrenElement) => { + let obj: any = childrenElement; + obj.upShow = false; + obj.required = childrenElement.itemProps.required; + obj.disabled = true; + obj.ifShow = true; + obj.label = `${optionsElement.label} - ${childrenElement.label}`; + obj.fieldName = childrenElement.componentProps.fieldName; + result.push(obj); + if (childrenElement.component === 'CardGroup') { + result = cardComponentChild(childrenElement.componentProps.options, result); + } + }); + }); + return result; +}; diff --git a/src/views/demo/workflow/task/completedTask.vue b/src/views/demo/workflow/task/completedTask.vue new file mode 100644 index 0000000..42ab4a6 --- /dev/null +++ b/src/views/demo/workflow/task/completedTask.vue @@ -0,0 +1,185 @@ + + + + diff --git a/src/views/demo/workflow/task/data.ts b/src/views/demo/workflow/task/data.ts new file mode 100644 index 0000000..e898ad9 --- /dev/null +++ b/src/views/demo/workflow/task/data.ts @@ -0,0 +1,164 @@ +import { FormSchema } from '@/components/Form'; + +export interface ListItem { + key: string; + title: string; + description: string; + extra?: string; + avatar?: string; + color?: string; +} + +// tab的list +export const settingList = [ + { + key: '1', + name: '待办任务', + component: 'UncompletedTask', + }, + { + key: '2', + name: '发起任务', + component: 'CreateFlow', + }, + { + key: '3', + name: '委托任务', + component: 'DelegateTask', + }, + { + key: '4', + name: '已办任务', + component: 'CompletedTask', + }, + { + key: '5', + name: '我的流程', + component: 'MyTask', + }, + { + key: '6', + name: '我的传阅', + component: 'ReadTask', + }, + { + key: '7', + name: '我的草稿', + component: 'MyDraft', + }, +]; + +// 基础设置 form +export const baseSetschemas: FormSchema[] = [ + { + field: 'email', + component: 'Input', + label: '邮箱', + colProps: { span: 18 }, + }, + { + field: 'name', + component: 'Input', + label: '昵称', + colProps: { span: 18 }, + }, + { + field: 'introduction', + component: 'InputTextArea', + label: '个人简介', + colProps: { span: 18 }, + }, + { + field: 'phone', + component: 'Input', + label: '联系电话', + colProps: { span: 18 }, + }, + { + field: 'address', + component: 'Input', + label: '所在地区', + colProps: { span: 18 }, + }, +]; + +// 安全设置 list +export const secureSettingList: ListItem[] = [ + { + key: '1', + title: '账户密码', + description: '当前密码强度::强', + extra: '修改', + }, + { + key: '2', + title: '密保手机', + description: '已绑定手机::138****8293', + extra: '修改', + }, + { + key: '3', + title: '密保问题', + description: '未设置密保问题,密保问题可有效保护账户安全', + extra: '修改', + }, + { + key: '4', + title: '备用邮箱', + description: '已绑定邮箱::ant***sign.com', + extra: '修改', + }, + { + key: '5', + title: 'MFA 设备', + description: '未绑定 MFA 设备,绑定后,可以进行二次确认', + extra: '修改', + }, +]; + +// 账号绑定 list +export const accountBindList: ListItem[] = [ + { + key: '1', + title: '绑定淘宝', + description: '当前未绑定淘宝账号', + extra: '绑定', + avatar: 'ri:taobao-fill', + color: '#ff4000', + }, + { + key: '2', + title: '绑定支付宝', + description: '当前未绑定支付宝账号', + extra: '绑定', + avatar: 'fa-brands:alipay', + color: '#2eabff', + }, + { + key: '3', + title: '绑定钉钉', + description: '当前未绑定钉钉账号', + extra: '绑定', + avatar: 'ri:dingding-fill', + color: '#2eabff', + }, +]; + +// 新消息通知 list +export const msgNotifyList: ListItem[] = [ + { + key: '1', + title: '账户密码', + description: '其他用户的消息将以站内信的形式通知', + }, + { + key: '2', + title: '系统消息', + description: '系统消息将以站内信的形式通知', + }, + { + key: '3', + title: '待办任务', + description: '待办任务将以站内信的形式通知', + }, +]; diff --git a/src/views/demo/workflow/task/delegateTask.vue b/src/views/demo/workflow/task/delegateTask.vue new file mode 100644 index 0000000..a0778ef --- /dev/null +++ b/src/views/demo/workflow/task/delegateTask.vue @@ -0,0 +1,154 @@ + + + + diff --git a/src/views/demo/workflow/task/i.js b/src/views/demo/workflow/task/i.js new file mode 100644 index 0000000..e69de29 diff --git a/src/views/demo/workflow/task/index.vue b/src/views/demo/workflow/task/index.vue new file mode 100644 index 0000000..c8db3ea --- /dev/null +++ b/src/views/demo/workflow/task/index.vue @@ -0,0 +1,80 @@ + + + + diff --git a/src/views/demo/workflow/task/myDraft.vue b/src/views/demo/workflow/task/myDraft.vue new file mode 100644 index 0000000..3b3c570 --- /dev/null +++ b/src/views/demo/workflow/task/myDraft.vue @@ -0,0 +1,157 @@ + + + + diff --git a/src/views/demo/workflow/task/myTask.vue b/src/views/demo/workflow/task/myTask.vue new file mode 100644 index 0000000..e6d96be --- /dev/null +++ b/src/views/demo/workflow/task/myTask.vue @@ -0,0 +1,214 @@ + + + + diff --git a/src/views/demo/workflow/task/page.ts b/src/views/demo/workflow/task/page.ts new file mode 100644 index 0000000..4831da5 --- /dev/null +++ b/src/views/demo/workflow/task/page.ts @@ -0,0 +1,7 @@ +export { default as CreateFlow } from '../create/index.vue'; +export { default as UncompletedTask } from './uncompletedTask.vue'; +export { default as CompletedTask } from './completedTask.vue'; +export { default as MyTask } from './myTask.vue'; +export { default as ReadTask } from './readTask.vue'; +export { default as MyDraft } from './myDraft.vue'; +export { default as DelegateTask } from './delegateTask.vue'; diff --git a/src/views/demo/workflow/task/process/audit.vue b/src/views/demo/workflow/task/process/audit.vue new file mode 100644 index 0000000..71b21eb --- /dev/null +++ b/src/views/demo/workflow/task/process/audit.vue @@ -0,0 +1,1339 @@ + + + + diff --git a/src/views/demo/workflow/task/process/auditInfo.vue b/src/views/demo/workflow/task/process/auditInfo.vue new file mode 100644 index 0000000..25a22e7 --- /dev/null +++ b/src/views/demo/workflow/task/process/auditInfo.vue @@ -0,0 +1,113 @@ + + + diff --git a/src/views/demo/workflow/task/process/initiate.vue b/src/views/demo/workflow/task/process/initiate.vue new file mode 100644 index 0000000..cc81218 --- /dev/null +++ b/src/views/demo/workflow/task/process/initiate.vue @@ -0,0 +1,474 @@ + + + + diff --git a/src/views/demo/workflow/task/process/look.vue b/src/views/demo/workflow/task/process/look.vue new file mode 100644 index 0000000..b7e3cc0 --- /dev/null +++ b/src/views/demo/workflow/task/process/look.vue @@ -0,0 +1,740 @@ + + + + diff --git a/src/views/demo/workflow/task/process/page.ts b/src/views/demo/workflow/task/process/page.ts new file mode 100644 index 0000000..663c9ad --- /dev/null +++ b/src/views/demo/workflow/task/process/page.ts @@ -0,0 +1,4 @@ +export { default as auditInfo } from './auditInfo.vue'; +export { default as Look } from './look.vue'; +export { default as Audit } from './audit.vue'; +export { default as Initiate } from './initiate.vue'; diff --git a/src/views/demo/workflow/task/process/processModel.ts b/src/views/demo/workflow/task/process/processModel.ts new file mode 100644 index 0000000..8f001c3 --- /dev/null +++ b/src/views/demo/workflow/task/process/processModel.ts @@ -0,0 +1,58 @@ +export interface logsType { + unitId: string; + name: string; + userIds: Array; + userNames: Array; + des: string; + time: string; + type: string; +} +export interface nodeUsersType { + id: string; + name: string; + options: { + value: string; + label: string; + }; +} +export interface taskBtnsType { + code: string; + name: string; + type: string; +} +export interface currentNodeObject { + [key: string]: any; +} + +export interface designerDataType { + loading: Boolean; + xmlString: ''; + height: string; + midVisible: Boolean; + isCustmerTitle: Boolean; + nodeUsers: nodeUsersType[]; + selectUsersVisible: Boolean; + selectTUserVisible: Boolean; + tUserType: Number; // 1 转移 2 加签, + isDraft: Boolean; + delegateUsers: []; + task: currentNodeObject; + process: currentNodeObject; + logs: logsType[]; // 流程日志信息 + nodeMap: {}; // 需要处理的任务 + userLogs: currentNodeObject[]; // 人员日志信息 + nodeLogs: currentNodeObject[]; + taskBtns: taskBtnsType[]; + currentNode: currentNodeObject; + stampList: []; + currentBtn: { + code: string; + name: string; + isNextAuditor: boolean; + }; + wfData: currentNodeObject[]; + isCreateAgain?: Boolean; + selectRejectNodeVisible: Boolean; + selectSignVisible: Boolean; + formCurrentNode: any; +} diff --git a/src/views/demo/workflow/task/process/selectAuditUsers.vue b/src/views/demo/workflow/task/process/selectAuditUsers.vue new file mode 100644 index 0000000..d2dc35f --- /dev/null +++ b/src/views/demo/workflow/task/process/selectAuditUsers.vue @@ -0,0 +1,36 @@ + + diff --git a/src/views/demo/workflow/task/process/selectRejectNode.vue b/src/views/demo/workflow/task/process/selectRejectNode.vue new file mode 100644 index 0000000..b6d7ce6 --- /dev/null +++ b/src/views/demo/workflow/task/process/selectRejectNode.vue @@ -0,0 +1,49 @@ + + diff --git a/src/views/demo/workflow/task/process/selectSign.vue b/src/views/demo/workflow/task/process/selectSign.vue new file mode 100644 index 0000000..3b7fb68 --- /dev/null +++ b/src/views/demo/workflow/task/process/selectSign.vue @@ -0,0 +1,168 @@ + + + + diff --git a/src/views/demo/workflow/task/readTask.vue b/src/views/demo/workflow/task/readTask.vue new file mode 100644 index 0000000..9b61852 --- /dev/null +++ b/src/views/demo/workflow/task/readTask.vue @@ -0,0 +1,166 @@ + + + + diff --git a/src/views/demo/workflow/task/uncompletedTask.vue b/src/views/demo/workflow/task/uncompletedTask.vue new file mode 100644 index 0000000..12cc31f --- /dev/null +++ b/src/views/demo/workflow/task/uncompletedTask.vue @@ -0,0 +1,211 @@ + + + + diff --git a/src/views/demo/workflow/task/wf.js b/src/views/demo/workflow/task/wf.js new file mode 100644 index 0000000..65e0a27 --- /dev/null +++ b/src/views/demo/workflow/task/wf.js @@ -0,0 +1,4 @@ +export default { + wfName:'handleWF', + name:'handleWF' +} \ No newline at end of file diff --git a/src/views/home/Files.vue b/src/views/home/Files.vue new file mode 100644 index 0000000..4755612 --- /dev/null +++ b/src/views/home/Files.vue @@ -0,0 +1,438 @@ + + + + diff --git a/src/views/home/LeftTree.vue b/src/views/home/LeftTree.vue new file mode 100644 index 0000000..1564d84 --- /dev/null +++ b/src/views/home/LeftTree.vue @@ -0,0 +1,75 @@ + + diff --git a/src/views/home/data.ts b/src/views/home/data.ts new file mode 100644 index 0000000..2d796f3 --- /dev/null +++ b/src/views/home/data.ts @@ -0,0 +1,79 @@ +import { BasicColumn, FormSchema } from '@/components/Table'; + +export const columns: BasicColumn[] = [ + { + title: '承包方编码', + dataIndex: 'cbfbm', + align: 'center', + width: 150, + }, + { + title: '权利人名称', + dataIndex: 'qlrmc', + align: 'center', + width: 100, + }, + { + title: '承包方成员数量', + dataIndex: 'cbfcysl', + align: 'center', + width: 100, + }, + { + title: '证件类型', + dataIndex: 'zjzl', + align: 'center', + width: 75, + }, + { + title: '证件号', + dataIndex: 'zjh', + align: 'center', + width: 150, + }, + { + title: '邮编', + dataIndex: 'yb', + align: 'center', + width: 100, + }, + { + title: '地址', + dataIndex: 'dz', + align: 'center', + width: 250, + }, + { + title: '承包地块总数', + dataIndex: 'cbdkzs', + align: 'center', + width: 75, + }, + { + title: '合同总面积', + dataIndex: 'htzmj', + align: 'center', + width: 100, + }, + { + title: '操作', + dataIndex: 'action', + align: 'center', + width: 80, + }, +]; + +export const searchFormSchema: FormSchema[] = [ + { + field: 'cbfbm', + label: '承包方编码', + component: 'Input', + colProps: { span: 6 }, + }, + { + field: 'qlrmc', + label: '权利人名称', + component: 'Input', + colProps: { span: 6 }, + }, +]; \ No newline at end of file diff --git a/src/views/home/index.vue b/src/views/home/index.vue new file mode 100644 index 0000000..657cc8a --- /dev/null +++ b/src/views/home/index.vue @@ -0,0 +1,164 @@ + + + diff --git a/src/views/map/dataScreen/index.vue b/src/views/map/dataScreen/index.vue new file mode 100644 index 0000000..b555340 --- /dev/null +++ b/src/views/map/dataScreen/index.vue @@ -0,0 +1,707 @@ + + + + + + diff --git a/src/views/map/dataScreen/util.ts b/src/views/map/dataScreen/util.ts new file mode 100644 index 0000000..684158a --- /dev/null +++ b/src/views/map/dataScreen/util.ts @@ -0,0 +1,9 @@ +export const enterpriseInfo = [ + {title:'法人',key:'legalPerson'}, + {title:'联系电话',key:'phone'}, + {title:'房产面积',key:'realEstateArea'}, + {title:'土地面积',key:'landArea'}, + {title:'类型',key:'type'}, + {title:'位置',key:'address'}, + {title:'测绘表',key:'surveySheet'}, +] \ No newline at end of file diff --git a/src/views/sys/error-log/DetailModal.vue b/src/views/sys/error-log/DetailModal.vue new file mode 100644 index 0000000..9390c04 --- /dev/null +++ b/src/views/sys/error-log/DetailModal.vue @@ -0,0 +1,27 @@ + + diff --git a/src/views/sys/error-log/data.tsx b/src/views/sys/error-log/data.tsx new file mode 100644 index 0000000..fc60d19 --- /dev/null +++ b/src/views/sys/error-log/data.tsx @@ -0,0 +1,67 @@ +import { Tag } from 'ant-design-vue'; +import { BasicColumn } from '@/components/Table'; +import { ErrorTypeEnum } from '@/enums/exceptionEnum'; +import { useI18n } from '@/hooks/web/useI18n'; + +const { t } = useI18n(); + +export function getColumns(): BasicColumn[] { + return [ + { + dataIndex: 'type', + title: t('sys.errorLog.tableColumnType'), + width: 80, + customRender: ({ text }) => { + const color = + text === ErrorTypeEnum.VUE + ? 'green' + : text === ErrorTypeEnum.RESOURCE + ? 'cyan' + : text === ErrorTypeEnum.PROMISE + ? 'blue' + : ErrorTypeEnum.AJAX + ? 'red' + : 'purple'; + return {() => text}; + }, + }, + { + dataIndex: 'url', + title: 'URL', + width: 200, + }, + { + dataIndex: 'time', + title: t('sys.errorLog.tableColumnDate'), + width: 160, + }, + { + dataIndex: 'file', + title: t('sys.errorLog.tableColumnFile'), + width: 200, + }, + { + dataIndex: 'name', + title: 'Name', + width: 200, + }, + { + dataIndex: 'message', + title: t('sys.errorLog.tableColumnMsg'), + width: 300, + }, + { + dataIndex: 'stack', + title: t('sys.errorLog.tableColumnStackMsg'), + }, + ]; +} + +export function getDescSchema(): any { + return getColumns().map((column) => { + return { + field: column.dataIndex!, + label: column.title, + }; + }); +} diff --git a/src/views/sys/error-log/index.vue b/src/views/sys/error-log/index.vue new file mode 100644 index 0000000..f49e12e --- /dev/null +++ b/src/views/sys/error-log/index.vue @@ -0,0 +1,97 @@ + + + diff --git a/src/views/sys/exception/Exception.vue b/src/views/sys/exception/Exception.vue new file mode 100644 index 0000000..1a7fcd5 --- /dev/null +++ b/src/views/sys/exception/Exception.vue @@ -0,0 +1,148 @@ + + diff --git a/src/views/sys/exception/index.ts b/src/views/sys/exception/index.ts new file mode 100644 index 0000000..5002c4a --- /dev/null +++ b/src/views/sys/exception/index.ts @@ -0,0 +1 @@ +export { default as Exception } from './Exception.vue'; diff --git a/src/views/sys/iframe/FrameBlank.vue b/src/views/sys/iframe/FrameBlank.vue new file mode 100644 index 0000000..99428bb --- /dev/null +++ b/src/views/sys/iframe/FrameBlank.vue @@ -0,0 +1,6 @@ + + diff --git a/src/views/sys/iframe/index.vue b/src/views/sys/iframe/index.vue new file mode 100644 index 0000000..7ada92e --- /dev/null +++ b/src/views/sys/iframe/index.vue @@ -0,0 +1,120 @@ + + + diff --git a/src/views/sys/lock/LockPage.vue b/src/views/sys/lock/LockPage.vue new file mode 100644 index 0000000..3dc2e54 --- /dev/null +++ b/src/views/sys/lock/LockPage.vue @@ -0,0 +1,237 @@ + + + diff --git a/src/views/sys/lock/index.vue b/src/views/sys/lock/index.vue new file mode 100644 index 0000000..4af9f81 --- /dev/null +++ b/src/views/sys/lock/index.vue @@ -0,0 +1,13 @@ + + diff --git a/src/views/sys/lock/useNow.ts b/src/views/sys/lock/useNow.ts new file mode 100644 index 0000000..dafc9ab --- /dev/null +++ b/src/views/sys/lock/useNow.ts @@ -0,0 +1,60 @@ +import { dateUtil } from '@/utils/dateUtil'; +import { reactive, toRefs } from 'vue'; +import { tryOnMounted, tryOnUnmounted } from '@vueuse/core'; + +export function 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/views/sys/login/ForgetPasswordForm.vue b/src/views/sys/login/ForgetPasswordForm.vue new file mode 100644 index 0000000..2905657 --- /dev/null +++ b/src/views/sys/login/ForgetPasswordForm.vue @@ -0,0 +1,83 @@ + + + diff --git a/src/views/sys/login/Login.vue b/src/views/sys/login/Login.vue new file mode 100644 index 0000000..f308da4 --- /dev/null +++ b/src/views/sys/login/Login.vue @@ -0,0 +1,236 @@ + + + diff --git a/src/views/sys/login/LoginForm.vue b/src/views/sys/login/LoginForm.vue new file mode 100644 index 0000000..5cb1143 --- /dev/null +++ b/src/views/sys/login/LoginForm.vue @@ -0,0 +1,322 @@ + + + diff --git a/src/views/sys/login/LoginFormTitle.vue b/src/views/sys/login/LoginFormTitle.vue new file mode 100644 index 0000000..3e4c9c4 --- /dev/null +++ b/src/views/sys/login/LoginFormTitle.vue @@ -0,0 +1,39 @@ + + + diff --git a/src/views/sys/login/MobileForm.vue b/src/views/sys/login/MobileForm.vue new file mode 100644 index 0000000..26169f8 --- /dev/null +++ b/src/views/sys/login/MobileForm.vue @@ -0,0 +1,63 @@ + + diff --git a/src/views/sys/login/QrCodeForm.vue b/src/views/sys/login/QrCodeForm.vue new file mode 100644 index 0000000..f27a73d --- /dev/null +++ b/src/views/sys/login/QrCodeForm.vue @@ -0,0 +1,31 @@ + + diff --git a/src/views/sys/login/RegisterForm.vue b/src/views/sys/login/RegisterForm.vue new file mode 100644 index 0000000..1af0572 --- /dev/null +++ b/src/views/sys/login/RegisterForm.vue @@ -0,0 +1,116 @@ + + + diff --git a/src/views/sys/login/SessionTimeoutLogin.vue b/src/views/sys/login/SessionTimeoutLogin.vue new file mode 100644 index 0000000..692ba65 --- /dev/null +++ b/src/views/sys/login/SessionTimeoutLogin.vue @@ -0,0 +1,54 @@ + + + diff --git a/src/views/sys/login/useLogin.ts b/src/views/sys/login/useLogin.ts new file mode 100644 index 0000000..ccaa2fb --- /dev/null +++ b/src/views/sys/login/useLogin.ts @@ -0,0 +1,130 @@ +import type { FormInstance } from 'ant-design-vue/lib/form/Form'; +import type { + RuleObject, + NamePath, + Rule as ValidationRule, +} from 'ant-design-vue/lib/form/interface'; +import { ref, computed, unref, Ref } from 'vue'; +import { useI18n } from '@/hooks/web/useI18n'; + +export enum LoginStateEnum { + LOGIN, + REGISTER, + RESET_PASSWORD, + MOBILE, + QR_CODE, +} + +const currentState = ref(LoginStateEnum.LOGIN); + +// 这里也可以优化 +// import { createGlobalState } from '@vueuse/core' + +export function useLoginState() { + function setLoginState(state: LoginStateEnum) { + currentState.value = state; + } + + const getLoginState = computed(() => currentState.value); + + function handleBackLogin() { + setLoginState(LoginStateEnum.LOGIN); + } + + return { setLoginState, getLoginState, handleBackLogin }; +} + +export function useFormValid(formRef: Ref) { + const validate = computed(() => { + const form = unref(formRef); + return form?.validate ?? ((_nameList?: NamePath) => Promise.resolve()); + }); + + async function validForm() { + const form = unref(formRef); + if (!form) return; + const data = await form.validate(); + return data as T; + } + + return { validate, validForm }; +} + +export function useFormRules(formData?: Recordable) { + const { t } = useI18n(); + + const getAccountFormRule = computed(() => createRule(t('sys.login.accountPlaceholder'))); + const getPasswordFormRule = computed(() => createRule(t('sys.login.passwordPlaceholder'))); + const getSmsFormRule = computed(() => createRule(t('sys.login.smsPlaceholder'))); + const getMobileFormRule = computed(() => createRule(t('sys.login.mobilePlaceholder'))); + + const validatePolicy = async (_: RuleObject, value: boolean) => { + return !value ? Promise.reject(t('sys.login.policyPlaceholder')) : Promise.resolve(); + }; + + const validateConfirmPassword = (password: string) => { + return async (_: RuleObject, value: string) => { + if (!value) { + return Promise.reject(t('sys.login.passwordPlaceholder')); + } + if (value !== password) { + return Promise.reject(t('sys.login.diffPwd')); + } + return Promise.resolve(); + }; + }; + + const getFormRules = computed((): { [k: string]: ValidationRule | ValidationRule[] } => { + const accountFormRule = unref(getAccountFormRule); + const passwordFormRule = unref(getPasswordFormRule); + const smsFormRule = unref(getSmsFormRule); + const mobileFormRule = unref(getMobileFormRule); + + const mobileRule = { + sms: smsFormRule, + mobile: mobileFormRule, + }; + switch (unref(currentState)) { + // register form rules + case LoginStateEnum.REGISTER: + return { + account: accountFormRule, + password: passwordFormRule, + confirmPassword: [ + { validator: validateConfirmPassword(formData?.password), trigger: 'change' }, + ], + policy: [{ validator: validatePolicy, trigger: 'change' }], + ...mobileRule, + }; + + // reset password form rules + case LoginStateEnum.RESET_PASSWORD: + return { + account: accountFormRule, + ...mobileRule, + }; + + // mobile form rules + case LoginStateEnum.MOBILE: + return mobileRule; + + // login form rules + default: + return { + account: accountFormRule, + password: passwordFormRule, + }; + } + }); + return { getFormRules }; +} + +function createRule(message: string): ValidationRule[] { + return [ + { + required: true, + message, + trigger: 'change', + }, + ]; +} diff --git a/src/views/sys/redirect/index.vue b/src/views/sys/redirect/index.vue new file mode 100644 index 0000000..9e6647b --- /dev/null +++ b/src/views/sys/redirect/index.vue @@ -0,0 +1,30 @@ + + diff --git a/src/views/systemForm/ceshi/index.vue b/src/views/systemForm/ceshi/index.vue new file mode 100644 index 0000000..d0f6301 --- /dev/null +++ b/src/views/systemForm/ceshi/index.vue @@ -0,0 +1,50 @@ + + diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..45a71de --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,30 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "extends": "@vben/ts-config/vue-app.json", + "compilerOptions": { + "baseUrl": ".", + "declaration": false, + "noUnusedLocals":false, + "types": ["vite/client","node"], + "paths": { + "@/*": ["src/*"], + "#/*": ["types/*"] + }, + "module": "ES2022", + "moduleResolution": "node" + }, + "include": [ + "tests/**/*.ts", + "src/**/*.ts", + "src/**/*.d.ts", + "src/**/*.tsx", + "src/**/*.vue", + "types/**/*.d.ts", + "types/**/*.ts", + "build/**/*.ts", + "build/**/*.d.ts", + "mock/**/*.ts", + "vite.config.ts" + ], + "exclude": ["node_modules", "tests/server/**/*.ts", "dist", "**/*.js"] +} diff --git a/turbo.json b/turbo.json new file mode 100644 index 0000000..bf5b89b --- /dev/null +++ b/turbo.json @@ -0,0 +1,18 @@ +{ + "$schema": "https://turborepo.org/schema.json", + "pipeline": { + "build": { + "dependsOn": ["^build"], + "outputs": ["dist/**"] + }, + "stub": {}, + "lint": {}, + "clean": { + "cache": false + }, + "dev": { + "cache": false, + "persistent": true + } + } +} diff --git a/types/axios.d.ts b/types/axios.d.ts new file mode 100644 index 0000000..0ff2f58 --- /dev/null +++ b/types/axios.d.ts @@ -0,0 +1,56 @@ +export type ErrorMessageMode = 'none' | 'modal' | 'message' | undefined; +export type SuccessMessageMode = ErrorMessageMode; + +export interface RequestOptions { + // Splicing request parameters to url + joinParamsToUrl?: boolean; + // Format request parameter time + formatDate?: boolean; + // Whether to process the request result + isTransformResponse?: boolean; + // Whether to return native response headers + // For example: use this attribute when you need to get the response headers + isReturnNativeResponse?: boolean; + // Whether to join url + joinPrefix?: boolean; + // Interface address, use the default apiUrl if you leave it blank + apiUrl?: string; + // 请求拼接路径 + urlPrefix?: string; + // Error message prompt type + errorMessageMode?: ErrorMessageMode; + // Success message prompt type + successMessageMode?: SuccessMessageMode; + // Whether to add a timestamp + joinTime?: boolean; + ignoreCancelToken?: boolean; + // Whether to send token in header + withToken?: boolean; + // 请求重试机制 + retryRequest?: RetryRequest; +} + +export interface RetryRequest { + isOpenRetry: boolean; + count: number; + waitTime: number; +} +export interface Result { + code: number; + type: 'success' | 'error' | 'warning'; + message: string; + result: T; +} + +// multipart/form-data: upload file +export interface UploadFileParams { + // Other parameters + data?: Recordable; + // File parameter interface field name + name?: string; + // file name + file: File | Blob; + // file name + filename?: string; + [key: string]: any; +} diff --git a/types/config.d.ts b/types/config.d.ts new file mode 100644 index 0000000..6a5c8dd --- /dev/null +++ b/types/config.d.ts @@ -0,0 +1,171 @@ +import { MenuTypeEnum, MenuModeEnum, TriggerEnum, MixSidebarTriggerEnum } from '@/enums/menuEnum'; +import { + ContentEnum, + PermissionModeEnum, + ThemeEnum, + RouterTransitionEnum, + SettingButtonPositionEnum, + SessionTimeoutProcessingEnum, +} from '@/enums/appEnum'; + +import { CacheTypeEnum } from '@/enums/cacheEnum'; + +export type LocaleType = 'zh_CN' | 'en' | 'ru' | 'ja' | 'ko'; + +export interface MenuSetting { + bgColor: string; + fixed: boolean; + collapsed: boolean; + siderHidden: boolean; + canDrag: boolean; + show: boolean; + hidden: boolean; + split: boolean; + menuWidth: number; + mode: MenuModeEnum; + type: MenuTypeEnum; + theme: ThemeEnum; + topMenuAlign: 'start' | 'center' | 'end'; + trigger: TriggerEnum; + accordion: boolean; + closeMixSidebarOnChange: boolean; + collapsedShowTitle: boolean; + mixSideTrigger: MixSidebarTriggerEnum; + mixSideFixed: boolean; +} + +export interface MultiTabsSetting { + cache: boolean; + show: boolean; + showQuick: boolean; + canDrag: boolean; + showRedo: boolean; + showFold: boolean; + autoCollapse: boolean; +} + +export interface HeaderSetting { + bgColor: string; + fixed: boolean; + show: boolean; + theme: ThemeEnum; + // Turn on full screen + showFullScreen: boolean; + // Whether to show the lock screen + useLockPage: boolean; + // Show document button + showDoc: boolean; + // Show message center button + showNotice: boolean; + showSearch: boolean; + showApi: boolean; +} + +export interface LocaleSetting { + showPicker: boolean; + // Current language + locale: LocaleType; + // default language + fallback: LocaleType; + // available Locales + availableLocales: LocaleType[]; +} + +export interface TransitionSetting { + // Whether to open the page switching animation + enable: boolean; + // Route basic switching animation + basicTransition: RouterTransitionEnum; + // Whether to open page switching loading + openPageLoading: boolean; + // Whether to open the top progress bar + openNProgress: boolean; +} + +export interface ProjectConfig { + // Storage location of permission related information + permissionCacheType: CacheTypeEnum; + // Whether to show the configuration button + showSettingButton: boolean; + // Whether to show the theme switch button + showDarkModeToggle: boolean; + // Configure where the button is displayed + settingButtonPosition: SettingButtonPositionEnum; + // Permission mode + permissionMode: PermissionModeEnum; + // Session timeout processing + sessionTimeoutProcessing: SessionTimeoutProcessingEnum; + // Website gray mode, open for possible mourning dates + grayMode: boolean; + // Whether to turn on the color weak mode + colorWeak: boolean; + // Theme color + themeColor: string; + + // The main interface is displayed in full screen, the menu is not displayed, and the top + fullContent: boolean; + // content width + contentMode: ContentEnum; + // Whether to display the logo + showLogo: boolean; + // Whether to show the global footer + showFooter: boolean; + // menuType: MenuTypeEnum; + headerSetting: HeaderSetting; + // menuSetting + menuSetting: MenuSetting; + // Multi-tab settings + multiTabsSetting: MultiTabsSetting; + // Animation configuration + transitionSetting: TransitionSetting; + // pageLayout whether to enable keep-alive + openKeepAlive: boolean; + // Lock screen time + lockTime: number; + // Show breadcrumbs + showBreadCrumb: boolean; + // Show breadcrumb icon + showBreadCrumbIcon: boolean; + // Use error-handler-plugin + useErrorHandle: boolean; + // Whether to open back to top + useOpenBackTop: boolean; + // Is it possible to embed iframe pages + canEmbedIFramePage: boolean; + // Whether to delete unclosed messages and notify when switching the interface + closeMessageOnSwitch: boolean; + // Whether to cancel the http request that has been sent but not responded when switching the interface. + removeAllHttpPending: boolean; +} + +export interface GlobConfig { + // Site title + title: string; + // Service interface url + apiUrl: string; + // Upload url + uploadUrl?: string; + // Service interface url prefix + urlPrefix?: string; + // Project abbreviation + shortName: string; +} +export interface GlobEnvConfig { + // Site title + VITE_GLOB_APP_TITLE: string; + // Site title English + VITE_GLOB_APP_EN_TITLE: string; + // Service interface url + VITE_GLOB_API_URL: string; + // Service interface url prefix + VITE_GLOB_API_URL_PREFIX?: string; + // Upload url + VITE_GLOB_UPLOAD_URL?: string; + // logo + VITE_GLOB_APP_LOGO?: string; + // info image video + VITE_GLOB_INFO_IMAGE_URL?: string; + VITE_GLOB_APP_MANAGEMENT_UNIT?: string; + VITE_GLOB_APP_TECHINICAL_SUPPORT?: string; + VITE_GLOB_APP_VERSIONS?: string; +} diff --git a/types/global.d.ts b/types/global.d.ts new file mode 100644 index 0000000..301c19a --- /dev/null +++ b/types/global.d.ts @@ -0,0 +1,98 @@ +import type { + ComponentRenderProxy, + VNode, + VNodeChild, + ComponentPublicInstance, + FunctionalComponent, + PropType as VuePropType, +} from 'vue'; + +declare global { + const __APP_INFO__: { + pkg: { + name: string; + version: string; + dependencies: Recordable; + devDependencies: Recordable; + }; + lastBuildTime: string; + }; + // declare interface Window { + // // Global vue app instance + // __APP__: App; + // } + + // fix FullScreen type error + interface Document { + mozFullScreenElement?: Element; + msFullscreenElement?: Element; + webkitFullscreenElement?: Element; + } + + // vue + declare type PropType = VuePropType; + declare type VueNode = VNodeChild | JSX.Element; + + export type Writable = { + -readonly [P in keyof T]: T[P]; + }; + + declare type Nullable = T | null; + declare type NonNullable = T extends null | undefined ? never : T; + declare type Recordable = Record; + declare type ReadonlyRecordable = { + readonly [key: string]: T; + }; + declare type Indexable = { + [key: string]: T; + }; + declare type DeepPartial = { + [P in keyof T]?: DeepPartial; + }; + declare type TimeoutHandle = ReturnType; + declare type IntervalHandle = ReturnType; + + declare interface ChangeEvent extends Event { + target: HTMLInputElement; + } + + declare interface WheelEvent { + path?: EventTarget[]; + } + interface ImportMetaEnv extends ViteEnv { + __: unknown; + } + + declare interface ViteEnv { + VITE_USE_MOCK: boolean; + VITE_PUBLIC_PATH: string; + VITE_GLOB_APP_TITLE: string; + VITE_BUILD_COMPRESS: 'gzip' | 'brotli' | 'none'; + } + + declare function parseInt(s: string | number, radix?: number): number; + + declare function parseFloat(string: string | number): number; + + namespace JSX { + // tslint:disable no-empty-interface + type Element = VNode; + // tslint:disable no-empty-interface + type ElementClass = ComponentRenderProxy; + interface ElementAttributesProperty { + $props: any; + } + interface IntrinsicElements { + [elem: string]: any; + } + interface IntrinsicAttributes { + [elem: string]: any; + } + } +} + +declare module 'vue' { + export type JSXComponent = + | { new (): ComponentPublicInstance } + | FunctionalComponent; +} diff --git a/types/index.d.ts b/types/index.d.ts new file mode 100644 index 0000000..7f67f33 --- /dev/null +++ b/types/index.d.ts @@ -0,0 +1,27 @@ +declare interface Fn { + (...arg: T[]): R; +} + +declare interface PromiseFn { + (...arg: T[]): Promise; +} + +declare type RefType = T | null; + +declare type LabelValueOptions = { + label: string; + value: any; + [key: string]: string | number | boolean; +}[]; + +declare type EmitType = ReturnType; + +declare type TargetContext = '_self' | '_blank'; + +declare interface ComponentElRef { + $el: T; +} + +declare type ComponentRef = ComponentElRef | null; + +declare type ElRef = Nullable; diff --git a/types/module.d.ts b/types/module.d.ts new file mode 100644 index 0000000..61a0c34 --- /dev/null +++ b/types/module.d.ts @@ -0,0 +1,18 @@ +declare module '*.vue' { + import { DefineComponent } from 'vue'; + + const Component: DefineComponent<{}, {}, any>; + export default Component; +} + +declare module 'ant-design-vue/es/locale/*' { + import { Locale } from 'ant-design-vue/types/locale-provider'; + + const locale: Locale & ReadonlyRecordable; + export default locale as Locale & ReadonlyRecordable; +} + +declare module 'virtual:*' { + const result: any; + export default result; +} diff --git a/types/store.d.ts b/types/store.d.ts new file mode 100644 index 0000000..754954a --- /dev/null +++ b/types/store.d.ts @@ -0,0 +1,61 @@ +import { ErrorTypeEnum } from '@/enums/exceptionEnum'; +import { MenuModeEnum, MenuTypeEnum } from '@/enums/menuEnum'; +import { RoleInfo } from '@/api/sys/model/userModel'; + +// Lock screen information +export interface LockInfo { + // Password required + pwd?: string | undefined; + // Is it locked? + isLock?: boolean; +} + +export interface ApiAddress { + key: string; + val: string; +} + +// Error-log information +export interface ErrorLogInfo { + // Type of error + type: ErrorTypeEnum; + // Error file + file: string; + // Error name + name?: string; + // Error message + message: string; + // Error stack + stack?: string; + // Error detail + detail: string; + // Error url + url: string; + // Error time + time?: string; +} + +export interface UserInfo { + id?: string | number; + userId: string | number; + username: string; + realName: string; + avatar: string; + desc?: string; + homePath?: string; + roles: RoleInfo[]; +} + +export interface BeforeMiniState { + menuCollapsed?: boolean; + menuSplit?: boolean; + menuMode?: MenuModeEnum; + menuType?: MenuTypeEnum; +} + +export interface TableSetting { + size: Nullable; + showIndexColumn: Recordable>; + columns: Recordable>>; + showRowSelection: Recordable>; +} diff --git a/types/utils.d.ts b/types/utils.d.ts new file mode 100644 index 0000000..77385e4 --- /dev/null +++ b/types/utils.d.ts @@ -0,0 +1,6 @@ +import type { ComputedRef, Ref } from 'vue'; + +// Ref类型 / ComputedRef类型 / T[P]泛型 +export type DynamicProps = { + [P in keyof T]: Ref | T[P] | ComputedRef; +}; diff --git a/types/vue-router.d.ts b/types/vue-router.d.ts new file mode 100644 index 0000000..b006c92 --- /dev/null +++ b/types/vue-router.d.ts @@ -0,0 +1,49 @@ +import { RoleEnum } from '@/enums/roleEnum'; + +export {}; + +declare module 'vue-router' { + interface RouteMeta extends Record { + orderNo?: number; + // title + title: string; + // dynamic router level. + dynamicLevel?: number; + // dynamic router real route path (For performance). + realPath?: string; + // Whether to ignore permissions + ignoreAuth?: boolean; + // role info + roles?: RoleEnum[]; + // Whether not to cache + ignoreKeepAlive?: boolean; + // Is it fixed on tab + affix?: boolean; + // icon on tab + icon?: string; + // img on tab + img?: string; + frameSrc?: string; + // current page transition + transitionName?: string; + // Whether the route has been dynamically added + hideBreadcrumb?: boolean; + // Hide submenu + hideChildrenInMenu?: boolean; + // Carrying parameters + carryParam?: boolean; + // Used internally to mark single-level menus + single?: boolean; + // Currently active menu + currentActiveMenu?: string; + // Never show in tab + hideTab?: boolean; + // Never show in menu + hideMenu?: boolean; + isLink?: boolean; + // only build for Menu + ignoreRoute?: boolean; + // Hide path for children + hidePathForChildren?: boolean; + } +} diff --git a/uno.config.ts b/uno.config.ts new file mode 100644 index 0000000..5e3512f --- /dev/null +++ b/uno.config.ts @@ -0,0 +1,5 @@ +import { defineConfig, presetTypography, presetUno } from 'unocss'; + +export default defineConfig({ + presets: [presetUno(), presetTypography()], +}); diff --git a/vite.config.ts b/vite.config.ts new file mode 100644 index 0000000..61a5558 --- /dev/null +++ b/vite.config.ts @@ -0,0 +1,61 @@ +import { defineApplicationConfig } from '@vben/vite-config'; + +export default defineApplicationConfig({ + overrides: { + optimizeDeps: { + include: [ + 'echarts/core', + 'echarts/charts', + 'echarts/components', + 'echarts/renderers', + 'qrcode', + '@iconify/iconify', + 'ant-design-vue/es/locale/zh_CN', + 'ant-design-vue/es/locale/en_US', + '@/../lib/vform/designer.umd.js', + ], + }, + build: { + /* 其他build生产打包配置省略 */ + //... + target: 'esnext', + commonjsOptions: { + include: /node_modules|lib/, //这里记得把lib目录加进来,否则生产打包会报错!! + }, + }, + server: { + proxy: { + '/basic-api': { + target: 'http://localhost:3000', + changeOrigin: true, + ws: true, + rewrite: (path) => path.replace(new RegExp(`^/basic-api`), ''), + // only https + // secure: false + }, + '/upload': { + target: 'http://localhost:3300/upload', + changeOrigin: true, + ws: true, + rewrite: (path) => path.replace(new RegExp(`^/upload`), ''), + }, + }, + warmup: { + clientFiles: ['./index.html', './src/{views,components}/*'], + }, + }, + define: { + 'process.env': { + BASE_URL: '/', + }, + }, + css: { + preprocessorOptions: { + less: { + javascriptEnabled: true, + }, + }, + }, + plugins: [], + }, +});