From d2946b256016255562beefdc9487a6ff104ae295 Mon Sep 17 00:00:00 2001 From: bqy_fe <1743369777@qq.com> Date: Tue, 4 May 2021 21:54:05 +0800 Subject: [PATCH] first commit --- .cz-config.js | 92 + .editorconfig | 16 + .env.development | 10 + .env.production | 10 + .eslintignore | 15 + .eslintrc.js | 60 + .github/workflows/deploy.yml | 29 + .gitignore | 47 + .husky/.gitignore | 1 + .husky/commit-msg | 4 + .husky/pre-commit | 4 + .husky/pre-push | 9 + .prettierignore | 9 + LICENSE | 21 + README.md | 41 + commitlint.config.js | 1 + index.html | 13 + package.json | 85 + prettier.config.js | 9 + public/favicon.ico | Bin 0 -> 4286 bytes src/App.vue | 48 + src/assets/logo.png | Bin 0 -> 60745 bytes src/common/types/index.ts | 5 + src/hooks/useGlobalProperties.ts | 27 + src/main.ts | 22 + src/packages/base-widgets/button/index.tsx | 137 + .../base-widgets/checkbox/createFieldProps.ts | 39 + src/packages/base-widgets/checkbox/index.tsx | 94 + .../datetimePicker/createFieldProps.ts | 39 + .../base-widgets/datetimePicker/index.tsx | 116 + src/packages/base-widgets/image/index.tsx | 32 + src/packages/base-widgets/index.ts | 11 + .../base-widgets/input/createFieldProps.ts | 141 + src/packages/base-widgets/input/index.tsx | 36 + src/packages/base-widgets/nav-bar/index.tsx | 46 + .../base-widgets/number-range/index.tsx | 31 + .../number-range/number-range.scss | 24 + .../number-range/number-range.tsx | 30 + .../base-widgets/picker/createFieldProps.ts | 39 + src/packages/base-widgets/picker/index.tsx | 113 + .../base-widgets/radio/createFieldProps.ts | 39 + src/packages/base-widgets/radio/index.tsx | 90 + .../base-widgets/rate/createFieldProps.ts | 39 + src/packages/base-widgets/rate/index.tsx | 60 + src/packages/base-widgets/select/index.tsx | 37 + .../base-widgets/slider/createFieldProps.ts | 39 + src/packages/base-widgets/slider/index.tsx | 61 + .../base-widgets/stepper/createFieldProps.ts | 39 + src/packages/base-widgets/stepper/index.tsx | 55 + .../base-widgets/switch/createFieldProps.ts | 39 + src/packages/base-widgets/switch/index.tsx | 55 + src/packages/base-widgets/text/index.tsx | 28 + .../form/index.module.scss | 10 + .../container-component/form/index.tsx | 54 + src/packages/container-component/index.ts | 11 + .../layout/index.module.scss | 10 + .../container-component/layout/index.tsx | 115 + src/plugins/element-plus.ts | 3 + src/plugins/vant.ts | 2 + src/router/index.ts | 10 + src/shims-vue.d.ts | 32 + src/store/index.ts | 27 + src/style/common.scss | 14 + src/visual-editor/components/common/monaco.ts | 24 + .../components/common/simulator.vue | 43 + .../components/header/comp-render.tsx | 27 + src/visual-editor/components/header/index.vue | 67 + .../components/header/preview.vue | 94 + .../components/header/slot-item.vue | 40 + .../components/base-widgets/index.module.scss | 43 + .../components/base-widgets/index.tsx | 45 + .../container-component/index.module.scss | 43 + .../components/container-component/index.tsx | 45 + .../components/custom-component/index.vue | 10 + .../components/left-aside/components/index.ts | 13 + .../left-aside/components/page-tree/index.vue | 75 + .../components/page-tree/treeData.ts | 57 + .../components/left-aside/index.vue | 63 + .../components/left-aside/tabs.ts | 26 + .../MonacoEditor.module.scss | 20 + .../right-attribute-panel/MonacoEditor.tsx | 138 + .../table-prop-edit.service.tsx | 132 + .../table-prop-editor/table-prop-editor.tsx | 38 + .../right-attribute-panel/index.common.scss | 17 + .../right-attribute-panel/index.module.scss | 61 + .../right-attribute-panel/index.tsx | 177 + .../simulator-editor/comp-render.tsx | 28 + .../draggable-transition-group.vue | 95 + .../simulator-editor/simulator-editor.vue | 229 + .../components/simulator-editor/slot-item.vue | 137 + src/visual-editor/index.vue | 108 + src/visual-editor/plugins/command.plugin.ts | 156 + src/visual-editor/plugins/event.ts | 17 + src/visual-editor/plugins/keyboard-code.ts | 71 + src/visual-editor/utils/defer.ts | 22 + src/visual-editor/utils/dialog-service.tsx | 134 + src/visual-editor/utils/dropdown-service.tsx | 143 + .../utils/dropdown-sservice.scss | 29 + src/visual-editor/utils/useDotProp.ts | 18 + src/visual-editor/utils/useModel.tsx | 42 + src/visual-editor/visual-editor.props.tsx | 148 + src/visual-editor/visual-editor.utils.ts | 160 + src/visual-editor/visual.command.tsx | 232 + src/visual.config.tsx | 16 + tsconfig.json | 38 + vite.config.ts | 73 + windi.config.ts | 38 + yarn.lock | 4815 +++++++++++++++++ 108 files changed, 10422 insertions(+) create mode 100644 .cz-config.js create mode 100644 .editorconfig create mode 100644 .env.development create mode 100644 .env.production create mode 100644 .eslintignore create mode 100644 .eslintrc.js create mode 100644 .github/workflows/deploy.yml create mode 100644 .gitignore create mode 100644 .husky/.gitignore create mode 100644 .husky/commit-msg create mode 100644 .husky/pre-commit create mode 100644 .husky/pre-push create mode 100644 .prettierignore create mode 100644 LICENSE create mode 100644 README.md create mode 100644 commitlint.config.js create mode 100644 index.html create mode 100644 package.json create mode 100644 prettier.config.js create mode 100644 public/favicon.ico create mode 100644 src/App.vue create mode 100644 src/assets/logo.png create mode 100644 src/common/types/index.ts create mode 100644 src/hooks/useGlobalProperties.ts create mode 100644 src/main.ts create mode 100644 src/packages/base-widgets/button/index.tsx create mode 100644 src/packages/base-widgets/checkbox/createFieldProps.ts create mode 100644 src/packages/base-widgets/checkbox/index.tsx create mode 100644 src/packages/base-widgets/datetimePicker/createFieldProps.ts create mode 100644 src/packages/base-widgets/datetimePicker/index.tsx create mode 100644 src/packages/base-widgets/image/index.tsx create mode 100644 src/packages/base-widgets/index.ts create mode 100644 src/packages/base-widgets/input/createFieldProps.ts create mode 100644 src/packages/base-widgets/input/index.tsx create mode 100644 src/packages/base-widgets/nav-bar/index.tsx create mode 100644 src/packages/base-widgets/number-range/index.tsx create mode 100644 src/packages/base-widgets/number-range/number-range.scss create mode 100644 src/packages/base-widgets/number-range/number-range.tsx create mode 100644 src/packages/base-widgets/picker/createFieldProps.ts create mode 100644 src/packages/base-widgets/picker/index.tsx create mode 100644 src/packages/base-widgets/radio/createFieldProps.ts create mode 100644 src/packages/base-widgets/radio/index.tsx create mode 100644 src/packages/base-widgets/rate/createFieldProps.ts create mode 100644 src/packages/base-widgets/rate/index.tsx create mode 100644 src/packages/base-widgets/select/index.tsx create mode 100644 src/packages/base-widgets/slider/createFieldProps.ts create mode 100644 src/packages/base-widgets/slider/index.tsx create mode 100644 src/packages/base-widgets/stepper/createFieldProps.ts create mode 100644 src/packages/base-widgets/stepper/index.tsx create mode 100644 src/packages/base-widgets/switch/createFieldProps.ts create mode 100644 src/packages/base-widgets/switch/index.tsx create mode 100644 src/packages/base-widgets/text/index.tsx create mode 100644 src/packages/container-component/form/index.module.scss create mode 100644 src/packages/container-component/form/index.tsx create mode 100644 src/packages/container-component/index.ts create mode 100644 src/packages/container-component/layout/index.module.scss create mode 100644 src/packages/container-component/layout/index.tsx create mode 100644 src/plugins/element-plus.ts create mode 100644 src/plugins/vant.ts create mode 100644 src/router/index.ts create mode 100644 src/shims-vue.d.ts create mode 100644 src/store/index.ts create mode 100644 src/style/common.scss create mode 100644 src/visual-editor/components/common/monaco.ts create mode 100644 src/visual-editor/components/common/simulator.vue create mode 100644 src/visual-editor/components/header/comp-render.tsx create mode 100644 src/visual-editor/components/header/index.vue create mode 100644 src/visual-editor/components/header/preview.vue create mode 100644 src/visual-editor/components/header/slot-item.vue create mode 100644 src/visual-editor/components/left-aside/components/base-widgets/index.module.scss create mode 100644 src/visual-editor/components/left-aside/components/base-widgets/index.tsx create mode 100644 src/visual-editor/components/left-aside/components/container-component/index.module.scss create mode 100644 src/visual-editor/components/left-aside/components/container-component/index.tsx create mode 100644 src/visual-editor/components/left-aside/components/custom-component/index.vue create mode 100644 src/visual-editor/components/left-aside/components/index.ts create mode 100644 src/visual-editor/components/left-aside/components/page-tree/index.vue create mode 100644 src/visual-editor/components/left-aside/components/page-tree/treeData.ts create mode 100644 src/visual-editor/components/left-aside/index.vue create mode 100644 src/visual-editor/components/left-aside/tabs.ts create mode 100644 src/visual-editor/components/right-attribute-panel/MonacoEditor.module.scss create mode 100644 src/visual-editor/components/right-attribute-panel/MonacoEditor.tsx create mode 100644 src/visual-editor/components/right-attribute-panel/components/table-prop-editor/table-prop-edit.service.tsx create mode 100644 src/visual-editor/components/right-attribute-panel/components/table-prop-editor/table-prop-editor.tsx create mode 100644 src/visual-editor/components/right-attribute-panel/index.common.scss create mode 100644 src/visual-editor/components/right-attribute-panel/index.module.scss create mode 100644 src/visual-editor/components/right-attribute-panel/index.tsx create mode 100644 src/visual-editor/components/simulator-editor/comp-render.tsx create mode 100644 src/visual-editor/components/simulator-editor/draggable-transition-group.vue create mode 100644 src/visual-editor/components/simulator-editor/simulator-editor.vue create mode 100644 src/visual-editor/components/simulator-editor/slot-item.vue create mode 100644 src/visual-editor/index.vue create mode 100644 src/visual-editor/plugins/command.plugin.ts create mode 100644 src/visual-editor/plugins/event.ts create mode 100644 src/visual-editor/plugins/keyboard-code.ts create mode 100644 src/visual-editor/utils/defer.ts create mode 100644 src/visual-editor/utils/dialog-service.tsx create mode 100644 src/visual-editor/utils/dropdown-service.tsx create mode 100644 src/visual-editor/utils/dropdown-sservice.scss create mode 100644 src/visual-editor/utils/useDotProp.ts create mode 100644 src/visual-editor/utils/useModel.tsx create mode 100644 src/visual-editor/visual-editor.props.tsx create mode 100644 src/visual-editor/visual-editor.utils.ts create mode 100644 src/visual-editor/visual.command.tsx create mode 100644 src/visual.config.tsx create mode 100644 tsconfig.json create mode 100644 vite.config.ts create mode 100644 windi.config.ts create mode 100644 yarn.lock diff --git a/.cz-config.js b/.cz-config.js new file mode 100644 index 0000000..e11895c --- /dev/null +++ b/.cz-config.js @@ -0,0 +1,92 @@ +module.exports = { + // type 类型(定义之后,可通过上下键选择) + types: [ + { value: 'feat', name: 'feat: 新增功能' }, + { value: 'fix', name: 'fix: 修复 bug' }, + { value: 'docs', name: 'docs: 文档变更' }, + { + value: 'style', + name: 'style: 代码格式(不影响功能,例如空格、分号等格式修正)' + }, + { + value: 'refactor', + name: 'refactor: 代码重构(不包括 bug 修复、功能新增)' + }, + { value: 'perf', name: 'perf: 性能优化' }, + { value: 'test', name: 'test: 添加、修改测试用例' }, + { + value: 'build', + name: + 'build: 构建流程、外部依赖变更(如升级 npm 包、修改 webpack 配置等)' + }, + { value: 'ci', name: 'ci: 修改 CI 配置、脚本' }, + { + value: 'chore', + name: 'chore: 对构建过程或辅助工具和库的更改(不影响源文件、测试用例)' + }, + { value: 'revert', name: 'revert: 回滚 commit' } + ], + + // scope 类型(定义之后,可通过上下键选择) + scopes: [ + ['components', '组件相关'], + ['hooks', 'hook 相关'], + ['utils', 'utils 相关'], + ['element-ui', '对 element-ui 的调整'], + ['styles', '样式相关'], + ['deps', '项目依赖'], + ['auth', '对 auth 修改'], + ['other', '其他修改'], + // 如果选择 custom,后面会让你再输入一个自定义的 scope。也可以不设置此项,把后面的 allowCustomScopes 设置为 true + ['custom', '以上都不是?我要自定义'] + ].map(([value, description]) => { + return { + value, + name: `${value.padEnd(30)} (${description})` + } + }), + + // 是否允许自定义填写 scope,在 scope 选择的时候,会有 empty 和 custom 可以选择。 + // allowCustomScopes: true, + + // allowTicketNumber: false, + // isTicketNumberRequired: false, + // ticketNumberPrefix: 'TICKET-', + // ticketNumberRegExp: '\\d{1,5}', + + // 针对每一个 type 去定义对应的 scopes,例如 fix + /* + scopeOverrides: { + fix: [ + { name: 'merge' }, + { name: 'style' }, + { name: 'e2eTest' }, + { name: 'unitTest' } + ] + }, + */ + + // 交互提示信息 + messages: { + type: '确保本次提交遵循 Angular 规范!\n选择你要提交的类型:', + scope: '\n选择一个 scope(可选):', + // 选择 scope: custom 时会出下面的提示 + customScope: '请输入自定义的 scope:', + subject: '填写简短精炼的变更描述:\n', + body: '填写更加详细的变更描述(可选)。使用 "|" 换行:\n', + breaking: '列举非兼容性重大的变更(可选):\n', + footer: '列举出所有变更的 ISSUES CLOSED(可选)。 例如: #31, #34:\n', + confirmCommit: '确认提交?' + }, + + // 设置只有 type 选择了 feat 或 fix,才询问 breaking message + allowBreakingChanges: ['feat', 'fix'], + + // 跳过要询问的步骤 + // skipQuestions: ['body', 'footer'], + + subjectLimit: 100, // subject 限制长度 + breaklineChar: '|' // 换行符,支持 body 和 footer + // footerPrefix : 'ISSUES CLOSED:' + // askForBreakingChangeFirst : true, +} diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..6741efc --- /dev/null +++ b/.editorconfig @@ -0,0 +1,16 @@ +# Editor configuration, see http://editorconfig.org + +# 表示最顶层的 EditorConfig 配置文件 +root = true + +[*] # 表示所有文件适用 +charset = utf-8 # 设置文件字符集为 utf-8 +indent_style = space # 缩进风格(tab | space) +indent_size = 2 # 缩进大小 +end_of_line = lf # 控制换行类型(lf | cr | crlf) +trim_trailing_whitespace = true # 去除行首的任意空白字符 +insert_final_newline = true # 始终在文件末尾插入一个新行 + +[*.md] # 表示仅 md 文件适用以下规则 +max_line_length = off +trim_trailing_whitespace = false diff --git a/.env.development b/.env.development new file mode 100644 index 0000000..cfe99b3 --- /dev/null +++ b/.env.development @@ -0,0 +1,10 @@ +# 只在开发模式中被载入 + +# 网站前缀 +VITE_BASE_URL = / + +# 是否删除console +VITE_DROP_CONSOLE = true + +# API +VITE_APP_API_URL = http://29135jo738.zicp.vip/api/v1 diff --git a/.env.production b/.env.production new file mode 100644 index 0000000..823d5d5 --- /dev/null +++ b/.env.production @@ -0,0 +1,10 @@ +# 只在生产模式中被载入 + +# 网站前缀 +VITE_BASE_URL = /test + +# 是否删除console +VITE_DROP_CONSOLE = true + +# API +VITE_APP_API_URL = http://29135jo738.zicp.vip/api/v1 diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..348631b --- /dev/null +++ b/.eslintignore @@ -0,0 +1,15 @@ + +*.sh +node_modules +*.md +*.woff +*.ttf +.vscode +.idea +dist +/public +/docs +.husky +.local +/bin +Dockerfile diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000..999fffb --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,60 @@ +module.exports = { + root: true, + 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 + } + }, + extends: [ + 'plugin:vue/vue3-recommended', + 'plugin:@typescript-eslint/recommended', + 'prettier', + 'plugin:prettier/recommended' + ], + rules: { + 'vue/require-default-prop': 'off', + + '@typescript-eslint/ban-ts-comment': 'off', + '@typescript-eslint/no-explicit-any': 'off', + '@typescript-eslint/ban-types': 'off', + '@typescript-eslint/no-non-null-assertion': 'off', + '@typescript-eslint/explicit-module-boundary-types': 'off', + '@typescript-eslint/no-unused-vars': [ + 'error', + { + argsIgnorePattern: '^_', + varsIgnorePattern: '^_' + } + ], + 'no-unused-vars': [ + 'error', + { + argsIgnorePattern: '^_', + varsIgnorePattern: '^_' + } + ], + 'vue/html-self-closing': [ + 'error', + { + html: { + void: 'always', + normal: 'never', + component: 'always' + }, + svg: 'always', + math: 'always' + } + ] + }, + settings: {} +} diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 0000000..f964a33 --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,29 @@ +name: deploy + +on: + push: + branches: [main] + +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + - name: Setup Node.js v14.x + uses: actions/setup-node@v1 + with: + node-version: "14.x" + + - name: Install + run: npm install + + - name: Build + run: npm run build + + - name: Deploy + uses: peaceiris/actions-gh-pages@v3 + with: + publish_dir: ./dist + personal_token: ${{ secrets.PERSONAL_TOKEN }} + commit_message: Update ghPages diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..205ec07 --- /dev/null +++ b/.gitignore @@ -0,0 +1,47 @@ +# See http://help.github.com/ignore-files/ for more about ignoring files. + +# compiled output +/dist +/dist-ssr +/tmp +/out-tsc + +# dependencies +/node_modules +*.local +# yarn.lock +# package-lock.json + +# IDEs and editors +/.idea +.project +.classpath +.c9/ +*.launch +.settings/ +*.sublime-workspace + +# IDE - VSCode +.vscode/* +# !.vscode/settings.json +# !.vscode/tasks.json +# !.vscode/launch.json +# !.vscode/extensions.json + +# misc +/.sass-cache +/connect.lock +/coverage +/libpeerconnection.log +npm-debug.log +testem.log +/typings + +# e2e +/e2e/src/*.js +/e2e/src/*.map +/cypress/screenshots + +# System Files +.DS_Store +Thumbs.db diff --git a/.husky/.gitignore b/.husky/.gitignore new file mode 100644 index 0000000..31354ec --- /dev/null +++ b/.husky/.gitignore @@ -0,0 +1 @@ +_ diff --git a/.husky/commit-msg b/.husky/commit-msg new file mode 100644 index 0000000..617efbd --- /dev/null +++ b/.husky/commit-msg @@ -0,0 +1,4 @@ +#!/bin/sh +. "$(dirname "$0")/_/husky.sh" + +npx --no-install commitlint --edit diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100644 index 0000000..36af219 --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1,4 @@ +#!/bin/sh +. "$(dirname "$0")/_/husky.sh" + +npx lint-staged diff --git a/.husky/pre-push b/.husky/pre-push new file mode 100644 index 0000000..3aa50b6 --- /dev/null +++ b/.husky/pre-push @@ -0,0 +1,9 @@ +#!/bin/sh +. "$(dirname "$0")/_/husky.sh" + +npm run test + + + + + diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..f7e39e6 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,9 @@ +/dist/* +.local +.output.js +/node_modules/** + +**/*.svg +**/*.sh + +/public/* diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..c505514 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 buqiyuan + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..189e65a --- /dev/null +++ b/README.md @@ -0,0 +1,41 @@ +# Vite2.x + Vue3.x + TypeScript H5低代码平台 + +## 技术栈 + +- 编程语言:[TypeScript 4.x](https://www.typescriptlang.org/zh/) + [JavaScript](https://www.javascript.com/) +- 构建工具:[Vite 2.x](https://cn.vitejs.dev/) +- 前端框架:[Vue 3.x](https://v3.cn.vuejs.org/) +- 路由工具:[Vue Router 4.x](https://next.router.vuejs.org/zh/index.html) +- 状态管理:[Vuex 4.x](https://next.vuex.vuejs.org/) +- PC端UI 框架:[Element Plus](https://element-plus.org/#/zh-CN) +- H5端UI 框架:[vant](https://vant-contrib.gitee.io/vant/v3/#/zh-CN/) +- CSS 预编译:[Stylus](https://stylus-lang.com/) / [Sass](https://sass.bootcss.com/documentation) / [Less](http://lesscss.cn/) +- HTTP 工具:[Axios](https://axios-http.com/) +- Git Hook 工具:[husky](https://typicode.github.io/husky/#/) + [lint-staged](https://github.com/okonet/lint-staged) +- 代码规范:[EditorConfig](http://editorconfig.org) + [Prettier](https://prettier.io/) + [ESLint](https://eslint.org/) + [Airbnb JavaScript Style Guide](https://github.com/airbnb/javascript#translation) +- 提交规范:[Commitizen](http://commitizen.github.io/cz-cli/) + [Commitlint](https://commitlint.js.org/#/) +- 单元测试:[vue-test-utils](https://next.vue-test-utils.vuejs.org/) + [jest](https://jestjs.io/) + [vue-jest](https://github.com/vuejs/vue-jest) + [ts-jest](https://kulshekhar.github.io/ts-jest/) +- 自动部署:[GitHub Actions](https://docs.github.com/cn/actions/learn-github-actions) + +## 快速开始 + +### 安装依赖 + +```sh +npm install +# or +yarn add +``` + +### 启动项目 + +```sh +npm run dev +``` + +### 项目打包 + +```sh +npm run build +``` + diff --git a/commitlint.config.js b/commitlint.config.js new file mode 100644 index 0000000..4fedde6 --- /dev/null +++ b/commitlint.config.js @@ -0,0 +1 @@ +module.exports = { extends: ['@commitlint/config-conventional'] } diff --git a/index.html b/index.html new file mode 100644 index 0000000..11603f8 --- /dev/null +++ b/index.html @@ -0,0 +1,13 @@ + + +
+ + + +sBo7=5CPojne zlbz+FKD5~ns*LTX{{8{W$zwLxK3G*ty=+Sowur$p!;;3e%XH0x1ORe>|n#_shCHjLgiN z4$jW3AnvZ$@rjcCeag*arTr!bSZUy?y3zZ3BfAaR=q`_I;F@o>$MZ!#3Q{1LWol}w z3239S0mjo$6Kgg@jY!h4p4JPg@WtL_l7^N#y1HD`DNCFgQNPT86S(MyzjEM=418Ez z3T_wDw{r^zD2ZNn$slxTLM9sw;qEs@uGah15;2ngBwroc6o`N=N1&Jg{Oz-tk`;NE zl%(gj?``fmV P zlP);godX8!{<{}ETR6Hcw%@;CKycjH-=7AH=U1Q%5i5(+M*ZM~D&@P_utbO;j@;eN zD|@|^sdrm)bJ}0EN>#I@>sheK^`Q)WT)6IQbyxJq$a(rrtM=o_8KU+wJxECmHZ_Wyaz1b)XURd5XRM z-6Q{j!ulH#dy)!K(}5Hft2~Psnz4_+a`aOv-;@(CJc-g`)zXxoVxuS5aU%mu|&C zk1DwQ$G5uQx#IGbt-MT%-cWsi!UYGZtgg%aA_G)M-_U}7U@v!7YQG5(;f7*})`Kh0 z6FWu_lNrgJk68908Wyq+Ih!D1B|qi{Z^o}{4?c;QuZ?^T4r^?MGW+_%zvrgXG(w>W z$s_BQ@$a81?ItB_?vL#m`_&KyT5CE)-8NfNq{lEll*c!=ij5@@@7P<@T$N+?^X~=e z@J?AN2q5)8RS)cr);G3-V4s0x+pw*Al4W3n49Y <7Sgpv>NV(Bm zK2|O5^HJf;WB9_z{MVY^wLXh~-?=TbMQ(Bm^$p1uIVz#>-f-j%_ITufP1f)~)zR(d z!n#?1Y-UNz%l}rX)TqX$Y-Ry~RQFZFTCI-gb46B|Y*zD>PB(*VVqbNeiLs87b*Uao zn-mmp5=jXUfoC?m5E&mleS5iOJThEOKbOy41zf0Tt+O>Ja$U5!C&%maY&ZAQ0U3?> ze5H1)8HmT5O(aQUEY^!ks=I}_rnSF$?MJP49r7r%^X2lU)#gZzCi2MGWC0)8uj4$Y zXYa2r{POz(_3HcoHG|GKeEQ!k60r2=dwOV<3tDHk6%gTfw7*kIrUbHUW^vT)aZ+h{ zFQt50bRdO8#Ust}IMhx~lJZh%xfEoMA^MP3t7+Guq{dFnKIMG}Ucg16i`PT!{J#d> z^NsI6e !m3&&jJbQ#u|Y><)c&2KctqN-826sUy>`-2g6+3{$g z+^%Mos}Ssm^cDA=IZ#kSu0PCN*o=p@1GIL8M!x*@`S_F5?!NT(Kqrad4R)pbAjfp4 zQ^rC+ygx#X78p$|%HHL6^==ihw^gsrxnOJPZ4i(XnNJsM_HN55NiTH(zg`1?kg-pE z<&qa`b+le2@_8S}ZEvz(lj;21AGr$g4(UG@Mz#BMfIsHv%Z5dAj$IzIp#mzy8Z=;UT Z0!C!U 7pSx zb@LxP0fF#?fW|6x^Zj$LL4&DuQ-%QO;+K{KRvfSQ-#V{NC)f78L_7}jC|Z>wDYGUUs$P)<+5{G;Gc$gc? z!!hMYMA?+b4ts#sTUnxz-97?4UMe2MbznId?IC8+s!@;#ls&xJ0EQ=7?Q-Y&KxVBx zf8$$o3@UnihyQ*_WBW$aJc(=tvV<<|cAQwWTFelW9Tksk&Dt7`1*p};d{5~FB(&V4 zncNwaTvpIp1f^<>Icu%?IAYSl_}z>{!^KvQUp0$v&0g`rj3G#^MsH1Yy`NHSnRJ@p zU|hq>qPTXX4Q8@?!>02AxU~x`8Z`r7aReeZ{XTC>r^8k^7vRY o?uI6Zk5IRy!YoxLsre8@GKR z>^{&hq2T*+(Q+i4(m6q;Uxc4WIEQmFMM02u0-+u)<~FYIw0(3Ps!^>I?rt%Oyf2eX zPp>p=Rgk%S8g?HgJ_`x YE1VFdQKvnEOsLQuXCr B@F 0{I4olR?k6e^0x0VsQ*?a)VcbSsE9jJaz-bZ&04NwBfR8>7DB=l)B1d_zN1Qaz zt@{kw&8XzOOV4T^a9?cbjs~9>tp{6JVo0NqRo2^P*yCGZF_SZ%VN5s(#d~&CPz}-8 z_kOlmO>winpXLs2;;jjTlSf9O-HLbP^hGu%f`atFJlh7d*cCGxyVO8ed*JzRkpkOm z0q!fDYs6{sNGx $M4-Dk~Er&r*woU05sH+zkuT!n*ur5CE^we z4E&YK7w`R_4EDg)b`DrC(v}yvSl@4FzMf_PX%8PVc|F*wK5iT)Ms!BRs`#-)nn+-# zrV-#0jzMMIPdCcNDtw_J%$Rp;okN2gH<*_DgGMn2#{b7e?ni@3n&@=Pg>$|(@Pa)x z)VmW0iwj`eEk+Ed6hc|KHPp!np^3hBd15c1s;fge!>f{j$6n7c!;c9O=sXDc&zEqX zk&%+-2mTX>c|g0;PQNwjdLKN_SY9j+tqo}LU $eSt%9 zWTIllGRek>X;VzsdPlM>U6eqn(HFE6x}<3Fr;f{R)pIYPImGyQHeZG~%slt1i}x|E z;8#wS?vl0okjGK>5gIFT^5frFgs9<1t(|sXVk+riK&NTc)1g_%z{FIPWiNF@n|OcE z>_TV$ENtapk8g*L4T`~5dVrfeJWSwh%P5cIvpTgqo-dw|K` z=9e!IW12^*4>2jAPWwnXXTgmO&?A(QcBuio< xVLsqn>}=HWxYm1)%U^$0--L z;BQ4M@ObRA+Eb)ho#l3c4FieKXz-ujo%QpOOI)`Bto;12?l81kZ!)C#^)0D7hB)Ff zn9rnmmIg>E=QU9NS|*GZ{?`0_kZQ;-#R !mXle0E J7$gk%S)FVhEs+EFC>febnb?Cej=BX{k{V$SD!RRM zXkp+u@~YDDY{gKu4n7T_V@Yr4_x=2*)4>V@H^a!|0STA)*V`Fvyl6r`m0x!28hr5u zQ*rUht15y(^~%A1L|q%xKkzeb*qt;$+E7!I<$Q)@h(S@He%aTNLQyJmL^rJV_oJ+1 zNy1tEF%PwnVb^-6 LhnkJb96h1hVAsPa;*u{>VGk1C=xHV)?wRC7oBHpF*^ zSi71nK8(RNy`T9oM|w4vW+_;4wueeUMMR}^vz`u=b+aw7`i_s^zK>k`wHiW0%+etg zMz~rMLR ;OP`kq`PyE>9bb?P8`YPZ$O HzWd#Z%E)SuSEa44o0Bz2n0E^70 z<8RBY^$g&bsD1zLgoZtiOlJ#VYqQ=aK`(PzFMkH^efLCq&Ib*MIE?Q7T$&UfgdC^~ z;XmfJu#6>Y!r+x~wCl_g*>Zmc+_6Dd4fskaZK5Fc2JB2s?N23Y){zbWSqv MxeERYaQn+4P+dfX}2 zY_#qFwJYb2`8%3WzFDuY6Yzoz7Bqq$btKLh^;n2D!HC*}OyYpHz|32)mE*@iTNi4* zIh@KojD>Hr|J`1ob8k&t8*hzOBDLX6Iq62|74%~&lZU0`hOJi(KqAl?_}r^wGZ4`s z1Pb@c(Fjq^kd?r7cXH=oqJm!0c6<%8a<50B#tx~`WNRJKlb2Y_!3ni{wmk7@z?%6+ z{RNcM9AL^DJ6RNw2D9f5bx`$-+yO*XGw`QP2$ptF`r#e`#Po(hc8SUJWE--U&|MTJ<32iQjV~&&i<(fZ2 zr;N+{ 3Knh4M}hU+>g%u{@ebk6uz$=j9>q5LpMoNYJAxXw1HtA zSfbHkCs+8*ymQrJ&Xf^ep &t?Qw}Lu&T1*53rqZB8f1VTIg443K$)cD1WXSbYvHOhCCt$VV&8%zdqTI z(dqe!q><~MU(Ca IB9 +r9qd?)M}0+Pl+ma|c4(}nvHI^ (%Jw8# zq*j?WS@am;$!rC9jUB-Y+_ n73kXzfKh*lJiA*$P}fhqA}@&)b6NLq$IYI !b{bPivcF7HjkbX}V@#aIBqlhpn zncIiDTVY9jI`|7dC$mEjk*exki~Fzr$0fB)3hha%E2MP2G;U1Jxxce16|yE)h#`iA zv$N1#jZX)16nvu2Syny-`7~N1c@_O;#E*tBuuz)WFOfMCeqtWI6W)QfIQ;W%d|L`P zBBUu{VPJ)(;deXVcPXG{nHSHX(C5t~#6~ay;;CM5$*d9BOw^u_r%W;_^e25OMvnW0 z&A64wB}N6%pldDV^bNwD)g4JJQQ8+?6%-r#q&f1t0A_12vz{8>$?wvZGUcw2fB&Jk zy%ZiNcLH$P9Nw!+I~6m^`w>Ea7yb#(tKr7oijjH;LXq>peListHf8W{pN`6NW1VTj zxy5Lv-kG3!#boYceu!(mraS)=A;=BHcY`58s*DGy57;00S0u_+?rgD?g_J#|VxK+e zMfyIc``5PyuSz~(1Fl(I{^*VXn%rU^Bv)3(Ct&<{lflylT&>94>>IwmNuN+<`;Sh# z>`39F(n^Z=^TG;TY4(Gm^jvquE38}6(V!vBRG|;TL~i0-4pa^;1-Tut3q zo&>rRtuN?+@|4arfV5BNK`JfP3R-T*Hm6BO>pbA(s{4YLqgSBeWjROsEvo9<($4 zge>dN^fv=3P@~+KiVfWBk4&{5p7Qr*f<;uN4D(R6NGiVd{Ma#oCQ^+uaU`_DX$p%4 zMWTCFeL~tbNZtIa-^`|vc;aw(Xdl_y1>mI?8j>oN&ukv~-wR+P?Ck?b5AJ>(Fv@$~ z>Yv{ok;~OWYwXnY>PZL)Naj%UpI&Lu>;>5eM1m2YI-UA*C0aEFb P+o|TeY312#mM=11kJp!DH6CO_5Y1V&azYNkj;u(s)4i>hDJ9gK>30?9)Gr9YAaL zUOPw)FBlSBV`nS>ceqsAbfYH4Yy)mHP6*?G@d_DfqIA_?NY_yCmrAircma3ixM7N1 z5SsSUxmj;r8BkVCL%?HwzQPxO4$v&y=%}d7VsTIUt$^<%i!Rfw5=+;h$M>zFP%`#; zD8 >lFhK02lLL~NF`q&-> 2qH{TP!bxV9p_EfL$R%eS#X6&K+4YO^)P=WEiV@)i3(x zf_4^(cz6hhWl$Omxi8^M+3-Uecf1cCA3aAI7nM{Xk5Ik&95p&|Bpg^(-l^bERs4RL z>6FG~ivc2)nDHO6*fB9ex^=J-UjVCwuqc(Cn?hpa&B zX0VfGM599*J=*|WhYZtuuF3V|*c$+0#%K%!z7F_(NT~t0X6ENW8~e@9wg&gR%Xe=a z{PU(2g9# eEpPWUlg-d#$cP_~dIO2T23ni^zQYNhw3o|dl7ULds|01~6&pSR z)Tm+7REX_Uzg&kh0mfL_yW_cm+UmwRYdwY&`L<=p I{ILV>d`|0lyH|3L#iu z^6K-zYEs}%>tp7d@=~K;+6+t}zlfd8o4uNk#i5RdO4a`PV~ghm;yY?E>)jpBv{%V- z<8Vud`CHq06Jac%Gkj(7v*9Gq@8ccu%DAnb_5NaA(`tK1t{{j@B+7lQ!OX 2(R4gc~@+W51zwK^k=sjX8=a22~dp)ac0}+2MBa3e{oB`3ebOzWl@h zwduDqRyViXc^A+{CXxU>6Q0YE+In0NIf$*PxAVgliP7Vq 3ngdc$*s^`tNB>KE7&}?!Wy&eeW;N zEkOHi5W>BjyL Pr364t9fcvbidYKX#^-Cb| z!zE6E(d@ar0E(=afwOxxAOm=2#n!9cc4jP3CZ+p6rc>g6$jI6qa?A+c8hS9p{F%S$ z)y-HDzri5Ha|H1%gZNTy{BfL7RtffoqdUCcp6}@}EZ^^KjK@B@)1RZ&t3A2Uln&$0 zr=Rav41M6tTpCJ>i?xBps9e3<`zZ}7cW_Y5=4!id`Cpbusu>VCwSH`RlqT~yY^Fh* z;vjWFygX-l{Hq 2F0h)t(6=;?f(xLj{C@_I_c=NoJL->;Jq7NGU)z1!!d zIq8TYcH@GaEc}1JY#!S-py;hyMO9T2zCWe7+*0UzAJdvVy%*UZ1)qHoC>Jg@?5)~L z#gB|Q1oQ$Lo2Q!t;woVkJK(up2B6k>s{UDD{d~^=1heMM_=@n{rFI=S0Fd1{&{z*g zvjtkXj(bvd0JhC_M=a3L{kU>>vXFZYxP}Ehrs;2JPmISr2vdNwKxf?nC9ZBwOk3z$ z=+n`qDH!VQvEdtHm^_$S=T{k*+qu>mz>M(aF#iuY)>r@Y!i)nW rVWk1ySnCt>tl}@_>GbrPo=5QX9!E54DiQShWS2=Kv zN^t}ikcXy{hM5Okx_0+xD~gc5zaYwhn??#}c=8z0R7gy8l`5dumO-)4;CfgCzGGiq z5HNLX4nZZd{-+m0lLGDEbI(_WXix+US{_ M)@l`@VxVfA{?wTQYeoo@$uhQU zx`( 6rLp2`+jnfm+c^y*ZlRWAbR zQiRX(I9sMn0XsVXv(7l5=&SF>GXPwv0< 03 7j91tIHUWlcN1F#!isuQ;y0DFA$Fi6E2IX&6P^&?0TE0X`iM)@i9bgc&E` z@E a0L 6g>b$ z1;sO9O;X2*FQ18E4Tk#Xwp#{5(uXaDm}>`nv0s}jG;4GEFuwgEuW}x$Wq>+GGDWHq zs1h7$12zZ+;|UKv=rz&dPm~0rL--%p9nSl!-@#hH0RW_>-Fh<<7(5I!>`j9~wpf*Z zo1gqo{9n!y@)G$|w($5FF^=cu|9JY!uqd0p@1>>dqPrXEl %yyaIzD}Xer1{yFv!sD+1_|v{S1o>25 zJfM<-WgDPnIzL;<;sie#6pbrh>!bXke;-95_QK^gPRwpU;dCmPo5^j7hUlF;MX0 zf&XN}>o~P4a?fLrcz62qn7u=4cl4GkaG_k^JepkOU8pu5qdFzyuO{_8NgYsEQNfVy z+5G^%>1s@oN#_g!ACa<67TJzd?!TlDyD2Hhz3iZ=OfS_tSaR oY`VDr;iZQA|8RhscjpqqCiN1q{=@!CO7HiB>WGgM#*1=>Rnc?MLg?!&E z@b80$Vn-V-aBe@vO)@T?%{&)(#IlV5j7#$xH{kI%e~sI*PO@&0fBZ%nbARfyR6uod zTCKsALNFrw?EJ^KrC?8e|AFE5n)v$hE=Ir33K{tbuuFK^aH`n_%1c~ZdEpc|Kx7ll z7}o(czGXSvEHRi3Fl_bwlLTabjxqH|jU!(baK*>f8nupHVKEB8CG7Ot5`9!aA;J6l zNZS-_+XRaEOKR!;5EltChS=1*duh(CDQvTu^^7<4m56&Fu2qe0_0O$f2BieHE_06j zO?jt$tznJdqq{aX5v5rm (5AOvYxP1Q zq)XI(hJiSr6*eV3m*K-X+a8cocR}iqy`M0!>g1i+Xe0C005C-Z&OBPco$Q?w;3H?l zEJ%-=T~N=cS>@b08$J+wlH)M;ea5Eg9ZqHusf?5jSofRwwbhvS13_zDo!vQr?OpxB zC9oa&ryE55XolRUemXi6ypX|2;k?2>vHPdwo?tH(@7~dp?vD?sKz^;Je$R1|=bXCe zvFa2~H#Qk}@ZI~7U4t@#tc;X6f$g2rS9a}q3V?Y2c)8!Fz|*nn?+&vIC*SWZO-@g@ zGjtxJ8#YZ%gNyMOH@DUt23oapl?=X6*W%pgH}axa=v?r(6ROI5*XN1$dyYkwBnJ&x zmVZD7sl{a6wa8aS{cdlNvtAx>^MpI;XG@mGNM*qn->y*j`8=xelU^p=u;3TAV--3X z13075A%wEmESUF!&&*#XhThU~L%6*;R%(`Z@f4wG@J*66&D#aBqHm!)vDq0(Nrmq0 zwKgH!Kc9ZVk{vWV3E|vW$?B&*tAp~S2DbNHx8jcr +(P|p|? z(FKoeVfOpQ`iI*@+pT9b8l~@P5GuQR1~u%TD>;%(h$i0;c-%kY{k+{PTbu1;936lV zEUTE=Qx$2kaJp^tc%SjZ0psp5ZUWRm-orZ+*QN`!*iWDZxQH*o?2@7mryY$bM~Pos z_LaDwy^ShW-;C-UJ+mnXU!u|tyzx!2R<6fFZb$H0#7Se6FGb~1d*hPsx7UX=1IOc% z*$h7);4no^KKyFr-8if3qY)MY07*={!_i1r@9T_CG;_XhXt=qYff2EmNI8eSkuuQv z={|7vmQ48k(((7XYTC-2ENAXJYYSd;bEZ-%Cz(Lg7(atxm_=sbT|wN>arZ|DqxkNxIc-rh?9^*sU|mv@Nrgup zUNCTpcDp;@OigCF>d*2yZI%-eb~G8)XqWV|KWVC&U-R<`hP8Mil%0N1{NE?QjS^k& zD$@30(u;+C^tm~$>5ryh=qgXpH3 Qm~RP8qyH<}CzHp$Pd;uep$~X&$y37K~BtoTlROqqx7CtL-;bTmRo { zCsTK~KwFTWyyr~Xj;$5W0clFr{~%Ko9_nECodaxeB#7w@*>Xi1nRFKzi~fDORJ4!z zHYw _&GDhHrAEU1RfT?f*UWw1m*Mi>e5Su6wPk21zb=6#pnxp-A=F Th@0jCB0p&=^y7yn8a0(Y$9ahof^C! z%9kp4Z}YyM4T}#&CHQHXW)sZ0Qc1w}&f;HcvJQCPxK$9!lmxT^TuOX>$LKNN0bY#I zEbtE*3FJA}pu(pl#xc%cS;jgzS1M>el@@0odG3PJca| ah_mX+?*yPWK7S)NY#>&}m^nJlRz+6WW5z0k|cHt6D!jIoWK}_#`eNs_-iZBC? zkUCp{au|y}p42fpYb-JwgUn-OhRgS(4bsJ^W;m&1<<8A?n(WkFHJKJ62*J-m&yTmI zJegKH&E?Qoo@8(VsU23Fud`O0sxlUvs<+il#-FLLr$(P-CA28mK3Hz}E^JA^An~C3 zHY9 (5fqhD_xPMBp56z5WHB>oK`M$(rSeTBIVryzy ze9^gcG5&QXzNt!DqsxM7!xGfcB+Yhs>98)uJnzsSG{ZArrl*OEq- )c_x(qa@?n#C<2wGijvEBxBa=GDi0MIjR{RbIWt;;{h)R hvBtFzgSC4_s=aDSXSt_^iL&$h4$`0m}cfp#k|j&IwY^>tLnnm__SnL z?_dWZFxaS2MfbCB<=AN}CKJ*Eak^ <8eK;&;exo` C%txN&S z|9gbT%nJwx^cI6KX|)%AkJs9`%kbKr!9gW}M;I|Ns%wdr7Et!ZU^dr043ZWN8M-%% zaq$-iaL7BIzc0@ffGW|_9t_i{)eoxX5U!Rc&h@(&P35Q=+u<^5bVz$w7=}qvS=%^Q zq9OIG;5Ap=d^p(iOK~LP9Yg$cjZc==54Hhyzj_21d!#{olhe7DuMH-fu$W4;lVpCN zOEK;9Ak6+Neuf8XA!xaTzGIcnrlT`;3I&&i`~Y|nuTTq9%bF+I@4X^CcjCkQGM8LL zP`q&B#izzWMYwG1pMH`f$J0n9c`O2hPl0g@d20jKB@7HO`mTr5GIRShDCS@VnE_0L zd35A`0Uz1*vA}0O$_uDXG$;j$EYtp8#?i2|WARU&p}m-#?kp3DfBiXikojGA)Ti@M zEl=UE{?QXIpT=fM3Qsq{n%7q82C+^`croAjsCe%@qdPMEQnYC#LtYY5bH5lIF4h#F zaPElO;;e?k%W7Y$^B+Ac982O!?_L6Tq9knfPuYCF_QxAxw=A&I+5ZtRg8;r--wt-_ zyGz(s?%;6*NV;$oXPNo6Ylv*nr+jWw_3_OFnUA{b_J{f6K +-nPIc6xq-Z@T9f zYlEpot|x^uA}w^mlpN+48wktj!bojpGx-n0Ks1}vzpVN8FZ8?BK;}v{ r?D98S1rK`kk5mPNHA8 {puEAgG; z9RIhJnCDgvOp ZV#|H2T$PbsHu^@1*c>CyS+7H- 8{>z|Qv-(qC=p-+fgoR1xqn3~htqTo?#T#%FuSXb X<%8L1D(8_AfQXdbUZXHgWa4+QKFX{Da`UL6-S45S{S{*B z?ltY8e}))PLX(BLIt^cI4)6+hp4bcvBF6p3#<$ohlRmZhQuKCAXpu2;n<3`CvEOs@ zT$92!8aBR7JdSt;U~)@u-=Y)$o}T4eN&%?bYnBQw;kLO`_?~;2(b`r_dr+#vtQF&F z<;;hK>&?*WAS^r6k1V_T8tHcL_l9F@tdwIH#$3aJXmYvH;l)3H?{vn{NFd^GwM|H4 zRDs6I#Du-K{WSmuSetFEKOb%QAI(;n`#lW}9Ni-wKNXOs(Z1RramitrPW**CP_85? zh#`)Y Vm} z+DVsWY7sIQ? goy@4woz7tz1lq015sLQO z5OGB$lb!IjgmD8-Y6jlCjqWZx>-hVEhM?uOS4i)7pZqmg#Ww&x2%-Vy5GM_>uCzo- zB~uZUvl%Rssxkp% 7T)MZv?)xWiXbrZlyF$9Uy^z+6W(@M zl+g<+8viowr@6Cl+Vp5x^Q}c Vacj1Ym@2emwQoMu{6I z5_YbYU&J#Ea;3pImrP%Emh2-}T>N*k$cxOl6AWR+u6E4=C5+g= y5_A@^Y Kpmx?o}ZtyJZef{5DTl!}%z` caY+VB!mL(2NpJC7iHouqa zSp79Il_SU7M9XeH7)cD!c1-gABRd98miw$Aku6<7CJF~M)3WTd1Bgz@*4 q6(sc|gkk}S!|GbZ zN|{%@uuG#D<(hue7hJr_AxKSbr>nq>;64^b!Z*=n4<$!MSg7pT1(QMHq5~rVC-FX9 zDgbsjU)b@fY0 ;;Qvc}4Gc63PA0QxiWXPptb7kmW1xGQ+@eZ_mN(4K^C6 z5`<91g`*KoGyMl`{c{#=Hfvtc``)oVnW~= pWvoFuafMo(r*1>wi zfpzL4;+dOON7vY|VOjbu*sEeYey{v6ZUr?Rc5o=$^pi#AX+#}ZsQq>FYPY37%rj!d z2JZJcc2gnd&zg=I hd=aFk$;xhC?xOObIA( zpoS=cwlI8vuh817L~IlnPoL<#GWodI9cTgN8-~StjV;DuQAu<@BYYI6*2Is`*(s!z zg0OG9Se<8f|Ayh$r;R+eI- Tk$fIZNmzA~eWTObF>=w$% zSUKumIrm(W_5%um70#KRL~5MCPW;7fw+bb$*x$vyr2 L0*PnN@os$!(B5r*%RVyj?kHmmWM#tKay7;`w!hq^uk3(Ns Y0?UPV=vHGeL3f}YJ9=4CH1`9va!v8v;aWb3^O8-=ft!}K&as}`0VJ=tqc zA-VFv;rs)bgfa^$h|7ArpZ4lU9oAJ097rn>c5WA2wz&Q+8Ecw7KM9o&ly ye3B{n9UjvE Oam2Wp+BuL+U5! z0y?f%;ciHq3SLWCyoJs}rljGNxrIk>cN_hTf;o(cR=0ML1!7xab}(P@#Uk7@6isA) z1gQ8MsV!G$A^BXbdq2M=jsD{k6cQ0{*RWqMwAKs?!Vze{tuaPH_Phb zZ^^`%_H6_z>K&)bfBZ$sFRQc$aNK-1n0W9RRC^kvi7olPmS?l$-wvjGk<-wftAq%| z))@` (!y%-E%&Q- ) z$-tmjfQU})$_(V18)<8_G}&BkUkC-w3csXqkfc*_HsQD?xlC9X>DQ2F`f!-EWGm|k zkcM!SfeKcoZx1|fCZuk4))PAPyhYb^Uk&o#%5-PC>2Nuoq?Mp@4+r1k^yOyx{>f)@ zsnB~R9X)ybE~bmgPB!I^T4VC|r1O2PMMRn1^DmEeCWRpq?ndjwZ9xwFI91; 7`;YQ<~jA?#-inMb%^cEQx|PFUnYg z92GWZ7% zd@LVza!-ECbMWpMwRtDE0n4kfywzf}UX58pVnV`jjUjJbhM?0{ zQz~uO*&mI9LZ+6rZASqw_LdVaPT#vvcrSaANx3js*4P)Jf>VMND?ai6vA12l<&B8A z1-TJw$x@T6Cf!!Z;_%{WAQmiv2LPvKJk~S!g&mlO-K(=fg6MG>d6s{so2;lgn$*yT zp|rOL9|CK{2t=hExJv~TZaO^wn9&8KX4s+S;yP>SJ_xJoX8L&N$u4jB{QfhXrXX*C z)WQQ}mDzZLKf6%%g>uk(DCKtBdGz{ZN^@r<<29oR{dKW{r~e(0>w5g$8&LS#?z@a? zl77j>tuAW*c=%huJmae%Y%Z<~7GZ{!273l_QnDazD;mn??q&`rdAr#VPO73Ym~{7* z#E%J18V_mYVn6@0Y71WTJ+}>+2jRB-dy&hYnydK&mgpafMH*8g6z`Jf3t%4p!I!oP z1_Mb 0bx#(yYgSJmVogtSULE l1y!WpB*1GXII3 zHc0f*Ly @Z5h7H1eb6g_umk@Zlb@3%x(tZq`v7BVq>piA*89%6`lmH#N%BiS z6~iKoZTg4g0V?!iG9gz+CYWXwK(u-%riv1Zi+Ud9dY-l2_RehQxC;-CvNh1+n;r8| zX$FRrzzjlymKIOZIx{lZINVG{ >N}kHuI7K5dbccZho?s8WWwh=LcBDIOz*c{g-|HbP$eJ`kuS2p z4EK2_!|$nFEZWNxrgSB^4BhK#O~~o~rE7X(V6{O4)cg;i%f5u7yIwc*z%7WWp{ng~ zrFkOm_X@z7Z-(Moe_B+y{F!7?qrEH5%ue+Fd>I*gQPTVLZM+N~TjzGtD0H}FmL$<;kJxD!W8X~~JTg-wf|E;7U7|h|dgnpu z&1wQOQoArC)krxzf|2x-8u0?&ByvfGOb~no3jJa?p
AePrMqu~>O0t#+&N>yL3 zq0h<@G}*+FD4pf@hfbKQ+r90AKt0e2JbmTwI<;tFw!Lz z6cj9BojUQ@-d(-%nvLI|TiKkw-?>*pf*a(hS}+Pwp~LUyv{E&Lo}9Lv>0}7X&*Q#I zwZ%tEP1m2bN!{@lZv4@T$)juu4IZPliCg!*j9!tj9L8;>XiHQ<{TI!R$T7VzVO{Ht z)o*7WpWiXs9@qy22;a*b^+WXTOmf%i%|ww1VcRW&3*i52*@jrxea!i&$Lf&5mlaw4 zq0@Lk4heQNiYe sbJZ7yDY9tpIL5}f6%vJ}EgrF=0jzvi?&G$b( zVuN_D^1FkASgj+Ky3PM+YOuV}TVaaD(D_jBGU$06&@WSW#P!qK=*^3Xxi?y!cNKTX z{(>D-n^?&Q1H&;F-UbFy+9y}62i7zjn$>n^%hM@T_cDiyJjGJvUe0SYZE>VHvqp@H zCH}c5+HT{&ECdHPe^kfYG8)lpA?1B)e3abLt+MZ?k1YZ&SS}Ts0sq*F)7hN*UoGyD zPHNG(12Gi1Ki1t_7&Tg@b1xA-RpO8OCWbHE(|5gtY4l}xMt{>PRr}i#4iRmU`fnQn zG#l_+V(cQ1A^-nz@S( G3BYgpFYQckRSiMWuUwLH57t zT$U)~{oCw&nI?%mX2hwu+wgI?=;G{?Kp@}@)OlqJ2GwuaU-4Z~CH$V?4Jga ``THJts~LvWx;|JTd{3vTCgW&^fGt{s~q{3ybO<^h2jKA=W-xVq-wg zOD3X-II&>JF~kJIDNckK9TEF7bk 04P|qPE5g40wt@w zf&x|QQ!1)deL0mG8F&b<; C&z)HADa4r6Ob1RpowoTjn?D;`lt&;C_(e&~