From 77e9f1df5068c4de4f33204dfd87dcc68dc7a2cf Mon Sep 17 00:00:00 2001
From: alex_q <914269@qq.com>
Date: Fri, 12 Jun 2026 12:31:35 +0800
Subject: [PATCH] first commit
---
.editorconfig | 15 +
.env.development | 11 +
.env.production | 3 +
.eslintignore | 14 +
.eslintrc-auto-import.json | 309 +++++
.eslintrc.cjs | 88 ++
.gitignore | 18 +
.hintrc | 15 +
.husky/commit-msg | 1 +
.husky/pre-commit | 1 +
.prettierignore | 11 +
.prettierrc.cjs | 46 +
.stylelintignore | 11 +
.stylelintrc.cjs | 51 +
.vscode/extensions.json | 11 +
.vscode/settings.json | 80 ++
.vscode/vue3.0.code-snippets | 23 +
.vscode/vue3.2.code-snippets | 17 +
.vscode/vue3.3.code-snippets | 21 +
README.md | 191 +++
commitlint.config.cjs | 94 ++
index.html | 137 +++
mock/auth.mock.ts | 43 +
mock/base.ts | 10 +
mock/menu.mock.ts | 120 ++
mock/user.mock.ts | 44 +
package.json | 118 ++
public/favicon.ico | Bin 0 -> 16958 bytes
public/html/coin.html | 66 ++
public/html/contact.html | 23 +
public/html/help.css | 15 +
public/html/privacy.html | 156 +++
public/html/user.html | 120 ++
public/html/vip.html | 33 +
src/App.vue | 24 +
src/api/auth.ts | 150 +++
src/api/bank.ts | 28 +
src/api/codegen.ts | 191 +++
src/api/config.ts | 104 ++
src/api/dict.ts | 192 +++
src/api/file.ts | 74 ++
src/api/helper.ts | 86 ++
src/api/integral.ts | 56 +
src/api/log.ts | 122 ++
src/api/menu.ts | 209 ++++
src/api/message.ts | 57 +
src/api/notice.ts | 48 +
src/api/order.ts | 37 +
src/api/role.ts | 139 +++
src/api/software.ts | 130 ++
src/api/statistics.ts | 48 +
src/api/style.ts | 68 ++
src/api/user.ts | 612 ++++++++++
src/assets/icons/alipay-l.svg | 1 +
src/assets/icons/alipay-s.svg | 1 +
src/assets/icons/api.svg | 1 +
src/assets/icons/backtop.svg | 1 +
src/assets/icons/captcha.svg | 1 +
src/assets/icons/cascader.svg | 1 +
src/assets/icons/client.svg | 1 +
src/assets/icons/close.svg | 1 +
src/assets/icons/close_all.svg | 1 +
src/assets/icons/close_left.svg | 1 +
src/assets/icons/close_other.svg | 1 +
src/assets/icons/close_right.svg | 1 +
src/assets/icons/code.svg | 1 +
src/assets/icons/collapse.svg | 1 +
src/assets/icons/dict.svg | 1 +
src/assets/icons/document.svg | 1 +
src/assets/icons/download.svg | 1 +
src/assets/icons/file.svg | 1 +
src/assets/icons/finish-black.svg | 1 +
src/assets/icons/finish-white.svg | 1 +
src/assets/icons/fullscreen-exit.svg | 1 +
src/assets/icons/fullscreen.svg | 1 +
src/assets/icons/github.svg | 1 +
src/assets/icons/homepage.svg | 1 +
src/assets/icons/ip.svg | 1 +
src/assets/icons/java.svg | 1 +
src/assets/icons/language.svg | 1 +
src/assets/icons/menu.svg | 1 +
src/assets/icons/message.svg | 1 +
src/assets/icons/monitor.svg | 1 +
src/assets/icons/project.svg | 1 +
src/assets/icons/pv.svg | 1 +
src/assets/icons/qrcode-black.svg | 1 +
src/assets/icons/qrcode-white.svg | 1 +
src/assets/icons/refresh.svg | 1 +
src/assets/icons/role.svg | 1 +
src/assets/icons/scan-black.svg | 1 +
src/assets/icons/scan-white.svg | 1 +
src/assets/icons/setting.svg | 1 +
src/assets/icons/size.svg | 1 +
src/assets/icons/system.svg | 1 +
src/assets/icons/table.svg | 1 +
src/assets/icons/todo.svg | 1 +
src/assets/icons/tree.svg | 1 +
src/assets/icons/typescript.svg | 1 +
src/assets/icons/unipay.svg | 1 +
src/assets/icons/user.svg | 1 +
src/assets/icons/uv.svg | 1 +
src/assets/icons/vue.svg | 1 +
src/assets/icons/wxpay-l.svg | 1 +
src/assets/icons/wxpay-s.svg | 1 +
src/assets/icons/xml.svg | 1 +
src/assets/images/401.gif | Bin 0 -> 162867 bytes
src/assets/images/404.png | Bin 0 -> 20613 bytes
src/assets/images/404_cloud.png | Bin 0 -> 2644 bytes
src/assets/images/Software/ac_one_blur.png | Bin 0 -> 16557 bytes
src/assets/images/Software/ac_one_focus.png | Bin 0 -> 16967 bytes
src/assets/images/Software/android_qr.png | Bin 0 -> 27829 bytes
.../images/Software/icon_android_blur.png | Bin 0 -> 4049 bytes
.../images/Software/icon_android_focus.png | Bin 0 -> 4755 bytes
src/assets/images/Software/icon_download.png | Bin 0 -> 3125 bytes
src/assets/images/Software/icon_font.png | Bin 0 -> 10226 bytes
src/assets/images/Software/icon_ios_blur.png | Bin 0 -> 3835 bytes
src/assets/images/Software/icon_ios_focus.png | Bin 0 -> 4182 bytes
src/assets/images/Software/icon_pc_blur.png | Bin 0 -> 3665 bytes
src/assets/images/Software/icon_pc_focus.png | Bin 0 -> 4017 bytes
src/assets/images/Software/ios_qr2.png | Bin 0 -> 3096 bytes
src/assets/images/default.jpg | Bin 0 -> 16747 bytes
src/assets/images/flower.png | Bin 0 -> 1501 bytes
src/assets/images/hot_bank.jpg | Bin 0 -> 51653 bytes
src/assets/images/login-background-dark.jpg | Bin 0 -> 20471 bytes
src/assets/images/login-background-light.jpg | Bin 0 -> 32872 bytes
src/assets/images/sad.png | Bin 0 -> 982 bytes
src/assets/logo.png | Bin 0 -> 8953 bytes
src/assets/logo_s.png | Bin 0 -> 6418 bytes
src/assets/web_logo.png | Bin 0 -> 4691 bytes
src/components/AmountInput/index.vue | 70 ++
src/components/AppLink/index.vue | 38 +
src/components/Breadcrumb/index.vue | 97 ++
src/components/CURD/PageContent.vue | 1023 ++++++++++++++++
src/components/CURD/PageForm.vue | 174 +++
src/components/CURD/PageModal.vue | 425 +++++++
src/components/CURD/PageSearch.vue | 245 ++++
src/components/CURD/types.ts | 272 +++++
src/components/CURD/usePage.ts | 73 ++
src/components/CopyButton/index.vue | 62 +
src/components/Dictionary/index.vue | 76 ++
src/components/GithubCorner/index.vue | 62 +
src/components/Hamburger/index.vue | 39 +
src/components/IconSelect/index.vue | 208 ++++
src/components/IcpBar/index.vue | 52 +
src/components/LangSelect/index.vue | 47 +
src/components/LoginDialog/index.vue | 472 ++++++++
src/components/MenuSearch/index.vue | 143 +++
src/components/MsgTip/index.vue | 94 ++
src/components/Pagination/index.vue | 81 ++
src/components/SendCodeButton/index.vue | 147 +++
src/components/SizeSelect/index.vue | 39 +
src/components/SvgIcon/index.vue | 41 +
src/components/TableSelect/index.vue | 371 ++++++
src/components/TopBar/index.vue | 190 +++
src/components/Upload/FileUpload.vue | 331 ++++++
src/components/Upload/ImageUpload.vue | 280 +++++
src/components/WangEditor/index.vue | 81 ++
src/directive/index.ts | 9 +
src/directive/permission/index.ts | 38 +
src/enums/CacheEnum.ts | 4 +
src/enums/DeviceEnum.ts | 14 +
src/enums/DocumentTypeEnum.ts | 22 +
src/enums/FormTypeEnum.ts | 14 +
src/enums/LanguageEnum.ts | 14 +
src/enums/LayoutEnum.ts | 18 +
src/enums/MenuTypeEnum.ts | 22 +
src/enums/MessageTypeEnum.ts | 36 +
src/enums/NoticeTypeEnum.ts | 30 +
src/enums/QueryTypeEnum.ts | 37 +
src/enums/ResultEnum.ts | 23 +
src/enums/SidebarStatusEnum.ts | 14 +
src/enums/SizeEnum.ts | 19 +
src/enums/SoftwareEnum.ts | 81 ++
src/enums/ThemeEnum.ts | 18 +
src/lang/index.ts | 31 +
src/lang/package/en.ts | 64 +
src/lang/package/zh-cn.ts | 63 +
src/layout/components/AppMain/index.vue | 34 +
.../NavBar/components/NavbarAction.vue | 100 ++
src/layout/components/NavBar/index.vue | 30 +
.../Settings/components/LayoutSelect.vue | 108 ++
.../Settings/components/ThemeColorPicker.vue | 41 +
src/layout/components/Settings/index.vue | 123 ++
.../Sidebar/components/SidebarLogo.vue | 64 +
.../Sidebar/components/SidebarMenu.vue | 89 ++
.../Sidebar/components/SidebarMenuItem.vue | 202 ++++
.../components/SidebarMenuItemTitle.vue | 43 +
.../Sidebar/components/SidebarMixTopMenu.vue | 88 ++
src/layout/components/Sidebar/index.vue | 38 +
src/layout/components/TagsView/index.vue | 433 +++++++
src/layout/index.vue | 298 +++++
src/main.ts | 18 +
src/plugins/icons.ts | 9 +
src/plugins/index.ts | 24 +
src/plugins/permission.ts | 111 ++
src/router/index.ts | 168 +++
src/settings.ts | 26 +
src/store/index.ts | 16 +
src/store/modules/app.ts | 154 +++
src/store/modules/permission.ts | 88 ++
src/store/modules/settings.ts | 125 ++
src/store/modules/tagsView.ts | 253 ++++
src/store/modules/user.ts | 214 ++++
src/styles/index.scss | 33 +
src/styles/login.scss | 64 +
src/styles/reset.scss | 76 ++
src/styles/variables.module.scss | 12 +
src/styles/variables.scss | 40 +
src/types/auto-imports.d.ts | 1053 +++++++++++++++++
src/types/components.d.ts | 72 ++
src/types/env.d.ts | 40 +
src/types/global.d.ts | 95 ++
src/types/router.d.ts | 54 +
src/utils/baseurls.ts | 4 +
src/utils/device-type.ts | 28 +
src/utils/format.ts | 120 ++
src/utils/i18n.ts | 12 +
src/utils/index.ts | 51 +
src/utils/nprogress.ts | 18 +
src/utils/request.ts | 73 ++
src/views/account/messages/index.vue | 240 ++++
src/views/account/notes/index.vue | 3 +
src/views/account/notes/statement.vue | 144 +++
src/views/account/notes/trade.vue | 579 +++++++++
src/views/account/resetpwd/index.vue | 107 ++
src/views/account/security/index.vue | 506 ++++++++
src/views/account/vip/index.vue | 182 +++
src/views/autoLogin/index.vue | 50 +
src/views/dashboard/index.vue | 300 +++++
src/views/demo/internal-doc.vue | 28 +
.../children/children/level3-1.vue | 5 +
.../children/children/level3-2.vue | 5 +
.../demo/multi-level/children/level2.vue | 7 +
src/views/demo/multi-level/level1.vue | 15 +
src/views/demo/upload.vue | 215 ++++
src/views/demo/wang-editor.vue | 19 +
src/views/error-page/401.vue | 109 ++
src/views/error-page/404.vue | 242 ++++
src/views/helper/index.vue | 373 ++++++
src/views/redirect/index.vue | 15 +
src/views/resetPassword/index.vue | 330 ++++++
src/views/software/index.vue | 670 +++++++++++
src/views/system/config/index.vue | 327 +++++
src/views/system/dict/index.vue | 388 ++++++
src/views/system/log/index.vue | 123 ++
src/views/system/menu/index.vue | 632 ++++++++++
src/views/system/role/index.vue | 419 +++++++
.../system/user/components/user-import.vue | 131 ++
src/views/system/user/index.vue | 428 +++++++
src/views/website/audition/draw.vue | 209 ++++
src/views/website/audition/realname.vue | 261 ++++
src/views/website/notices/index.vue | 367 ++++++
src/views/website/question/index.vue | 477 ++++++++
src/views/website/statement/notes.vue | 162 +++
src/views/website/statement/orders.vue | 170 +++
src/views/website/statistics/index.vue | 331 ++++++
src/views/website/styles/index.vue | 405 +++++++
src/views/website/swVersions/index.vue | 619 ++++++++++
tsconfig.json | 27 +
uno.config.ts | 43 +
vite.config.ts | 239 ++++
261 files changed, 24791 insertions(+)
create mode 100644 .editorconfig
create mode 100644 .env.development
create mode 100644 .env.production
create mode 100644 .eslintignore
create mode 100644 .eslintrc-auto-import.json
create mode 100644 .eslintrc.cjs
create mode 100644 .gitignore
create mode 100644 .hintrc
create mode 100644 .husky/commit-msg
create mode 100644 .husky/pre-commit
create mode 100644 .prettierignore
create mode 100644 .prettierrc.cjs
create mode 100644 .stylelintignore
create mode 100644 .stylelintrc.cjs
create mode 100644 .vscode/extensions.json
create mode 100644 .vscode/settings.json
create mode 100644 .vscode/vue3.0.code-snippets
create mode 100644 .vscode/vue3.2.code-snippets
create mode 100644 .vscode/vue3.3.code-snippets
create mode 100644 README.md
create mode 100644 commitlint.config.cjs
create mode 100644 index.html
create mode 100644 mock/auth.mock.ts
create mode 100644 mock/base.ts
create mode 100644 mock/menu.mock.ts
create mode 100644 mock/user.mock.ts
create mode 100644 package.json
create mode 100644 public/favicon.ico
create mode 100644 public/html/coin.html
create mode 100644 public/html/contact.html
create mode 100644 public/html/help.css
create mode 100644 public/html/privacy.html
create mode 100644 public/html/user.html
create mode 100644 public/html/vip.html
create mode 100644 src/App.vue
create mode 100644 src/api/auth.ts
create mode 100644 src/api/bank.ts
create mode 100644 src/api/codegen.ts
create mode 100644 src/api/config.ts
create mode 100644 src/api/dict.ts
create mode 100644 src/api/file.ts
create mode 100644 src/api/helper.ts
create mode 100644 src/api/integral.ts
create mode 100644 src/api/log.ts
create mode 100644 src/api/menu.ts
create mode 100644 src/api/message.ts
create mode 100644 src/api/notice.ts
create mode 100644 src/api/order.ts
create mode 100644 src/api/role.ts
create mode 100644 src/api/software.ts
create mode 100644 src/api/statistics.ts
create mode 100644 src/api/style.ts
create mode 100644 src/api/user.ts
create mode 100644 src/assets/icons/alipay-l.svg
create mode 100644 src/assets/icons/alipay-s.svg
create mode 100644 src/assets/icons/api.svg
create mode 100644 src/assets/icons/backtop.svg
create mode 100644 src/assets/icons/captcha.svg
create mode 100644 src/assets/icons/cascader.svg
create mode 100644 src/assets/icons/client.svg
create mode 100644 src/assets/icons/close.svg
create mode 100644 src/assets/icons/close_all.svg
create mode 100644 src/assets/icons/close_left.svg
create mode 100644 src/assets/icons/close_other.svg
create mode 100644 src/assets/icons/close_right.svg
create mode 100644 src/assets/icons/code.svg
create mode 100644 src/assets/icons/collapse.svg
create mode 100644 src/assets/icons/dict.svg
create mode 100644 src/assets/icons/document.svg
create mode 100644 src/assets/icons/download.svg
create mode 100644 src/assets/icons/file.svg
create mode 100644 src/assets/icons/finish-black.svg
create mode 100644 src/assets/icons/finish-white.svg
create mode 100644 src/assets/icons/fullscreen-exit.svg
create mode 100644 src/assets/icons/fullscreen.svg
create mode 100644 src/assets/icons/github.svg
create mode 100644 src/assets/icons/homepage.svg
create mode 100644 src/assets/icons/ip.svg
create mode 100644 src/assets/icons/java.svg
create mode 100644 src/assets/icons/language.svg
create mode 100644 src/assets/icons/menu.svg
create mode 100644 src/assets/icons/message.svg
create mode 100644 src/assets/icons/monitor.svg
create mode 100644 src/assets/icons/project.svg
create mode 100644 src/assets/icons/pv.svg
create mode 100644 src/assets/icons/qrcode-black.svg
create mode 100644 src/assets/icons/qrcode-white.svg
create mode 100644 src/assets/icons/refresh.svg
create mode 100644 src/assets/icons/role.svg
create mode 100644 src/assets/icons/scan-black.svg
create mode 100644 src/assets/icons/scan-white.svg
create mode 100644 src/assets/icons/setting.svg
create mode 100644 src/assets/icons/size.svg
create mode 100644 src/assets/icons/system.svg
create mode 100644 src/assets/icons/table.svg
create mode 100644 src/assets/icons/todo.svg
create mode 100644 src/assets/icons/tree.svg
create mode 100644 src/assets/icons/typescript.svg
create mode 100644 src/assets/icons/unipay.svg
create mode 100644 src/assets/icons/user.svg
create mode 100644 src/assets/icons/uv.svg
create mode 100644 src/assets/icons/vue.svg
create mode 100644 src/assets/icons/wxpay-l.svg
create mode 100644 src/assets/icons/wxpay-s.svg
create mode 100644 src/assets/icons/xml.svg
create mode 100644 src/assets/images/401.gif
create mode 100644 src/assets/images/404.png
create mode 100644 src/assets/images/404_cloud.png
create mode 100644 src/assets/images/Software/ac_one_blur.png
create mode 100644 src/assets/images/Software/ac_one_focus.png
create mode 100644 src/assets/images/Software/android_qr.png
create mode 100644 src/assets/images/Software/icon_android_blur.png
create mode 100644 src/assets/images/Software/icon_android_focus.png
create mode 100644 src/assets/images/Software/icon_download.png
create mode 100644 src/assets/images/Software/icon_font.png
create mode 100644 src/assets/images/Software/icon_ios_blur.png
create mode 100644 src/assets/images/Software/icon_ios_focus.png
create mode 100644 src/assets/images/Software/icon_pc_blur.png
create mode 100644 src/assets/images/Software/icon_pc_focus.png
create mode 100644 src/assets/images/Software/ios_qr2.png
create mode 100644 src/assets/images/default.jpg
create mode 100644 src/assets/images/flower.png
create mode 100644 src/assets/images/hot_bank.jpg
create mode 100644 src/assets/images/login-background-dark.jpg
create mode 100644 src/assets/images/login-background-light.jpg
create mode 100644 src/assets/images/sad.png
create mode 100644 src/assets/logo.png
create mode 100644 src/assets/logo_s.png
create mode 100644 src/assets/web_logo.png
create mode 100644 src/components/AmountInput/index.vue
create mode 100644 src/components/AppLink/index.vue
create mode 100644 src/components/Breadcrumb/index.vue
create mode 100644 src/components/CURD/PageContent.vue
create mode 100644 src/components/CURD/PageForm.vue
create mode 100644 src/components/CURD/PageModal.vue
create mode 100644 src/components/CURD/PageSearch.vue
create mode 100644 src/components/CURD/types.ts
create mode 100644 src/components/CURD/usePage.ts
create mode 100644 src/components/CopyButton/index.vue
create mode 100644 src/components/Dictionary/index.vue
create mode 100644 src/components/GithubCorner/index.vue
create mode 100644 src/components/Hamburger/index.vue
create mode 100644 src/components/IconSelect/index.vue
create mode 100644 src/components/IcpBar/index.vue
create mode 100644 src/components/LangSelect/index.vue
create mode 100644 src/components/LoginDialog/index.vue
create mode 100644 src/components/MenuSearch/index.vue
create mode 100644 src/components/MsgTip/index.vue
create mode 100644 src/components/Pagination/index.vue
create mode 100644 src/components/SendCodeButton/index.vue
create mode 100644 src/components/SizeSelect/index.vue
create mode 100644 src/components/SvgIcon/index.vue
create mode 100644 src/components/TableSelect/index.vue
create mode 100644 src/components/TopBar/index.vue
create mode 100644 src/components/Upload/FileUpload.vue
create mode 100644 src/components/Upload/ImageUpload.vue
create mode 100644 src/components/WangEditor/index.vue
create mode 100644 src/directive/index.ts
create mode 100644 src/directive/permission/index.ts
create mode 100644 src/enums/CacheEnum.ts
create mode 100644 src/enums/DeviceEnum.ts
create mode 100644 src/enums/DocumentTypeEnum.ts
create mode 100644 src/enums/FormTypeEnum.ts
create mode 100644 src/enums/LanguageEnum.ts
create mode 100644 src/enums/LayoutEnum.ts
create mode 100644 src/enums/MenuTypeEnum.ts
create mode 100644 src/enums/MessageTypeEnum.ts
create mode 100644 src/enums/NoticeTypeEnum.ts
create mode 100644 src/enums/QueryTypeEnum.ts
create mode 100644 src/enums/ResultEnum.ts
create mode 100644 src/enums/SidebarStatusEnum.ts
create mode 100644 src/enums/SizeEnum.ts
create mode 100644 src/enums/SoftwareEnum.ts
create mode 100644 src/enums/ThemeEnum.ts
create mode 100644 src/lang/index.ts
create mode 100644 src/lang/package/en.ts
create mode 100644 src/lang/package/zh-cn.ts
create mode 100644 src/layout/components/AppMain/index.vue
create mode 100644 src/layout/components/NavBar/components/NavbarAction.vue
create mode 100644 src/layout/components/NavBar/index.vue
create mode 100644 src/layout/components/Settings/components/LayoutSelect.vue
create mode 100644 src/layout/components/Settings/components/ThemeColorPicker.vue
create mode 100644 src/layout/components/Settings/index.vue
create mode 100644 src/layout/components/Sidebar/components/SidebarLogo.vue
create mode 100644 src/layout/components/Sidebar/components/SidebarMenu.vue
create mode 100644 src/layout/components/Sidebar/components/SidebarMenuItem.vue
create mode 100644 src/layout/components/Sidebar/components/SidebarMenuItemTitle.vue
create mode 100644 src/layout/components/Sidebar/components/SidebarMixTopMenu.vue
create mode 100644 src/layout/components/Sidebar/index.vue
create mode 100644 src/layout/components/TagsView/index.vue
create mode 100644 src/layout/index.vue
create mode 100644 src/main.ts
create mode 100644 src/plugins/icons.ts
create mode 100644 src/plugins/index.ts
create mode 100644 src/plugins/permission.ts
create mode 100644 src/router/index.ts
create mode 100644 src/settings.ts
create mode 100644 src/store/index.ts
create mode 100644 src/store/modules/app.ts
create mode 100644 src/store/modules/permission.ts
create mode 100644 src/store/modules/settings.ts
create mode 100644 src/store/modules/tagsView.ts
create mode 100644 src/store/modules/user.ts
create mode 100644 src/styles/index.scss
create mode 100644 src/styles/login.scss
create mode 100644 src/styles/reset.scss
create mode 100644 src/styles/variables.module.scss
create mode 100644 src/styles/variables.scss
create mode 100644 src/types/auto-imports.d.ts
create mode 100644 src/types/components.d.ts
create mode 100644 src/types/env.d.ts
create mode 100644 src/types/global.d.ts
create mode 100644 src/types/router.d.ts
create mode 100644 src/utils/baseurls.ts
create mode 100644 src/utils/device-type.ts
create mode 100644 src/utils/format.ts
create mode 100644 src/utils/i18n.ts
create mode 100644 src/utils/index.ts
create mode 100644 src/utils/nprogress.ts
create mode 100644 src/utils/request.ts
create mode 100644 src/views/account/messages/index.vue
create mode 100644 src/views/account/notes/index.vue
create mode 100644 src/views/account/notes/statement.vue
create mode 100644 src/views/account/notes/trade.vue
create mode 100644 src/views/account/resetpwd/index.vue
create mode 100644 src/views/account/security/index.vue
create mode 100644 src/views/account/vip/index.vue
create mode 100644 src/views/autoLogin/index.vue
create mode 100644 src/views/dashboard/index.vue
create mode 100644 src/views/demo/internal-doc.vue
create mode 100644 src/views/demo/multi-level/children/children/level3-1.vue
create mode 100644 src/views/demo/multi-level/children/children/level3-2.vue
create mode 100644 src/views/demo/multi-level/children/level2.vue
create mode 100644 src/views/demo/multi-level/level1.vue
create mode 100644 src/views/demo/upload.vue
create mode 100644 src/views/demo/wang-editor.vue
create mode 100644 src/views/error-page/401.vue
create mode 100644 src/views/error-page/404.vue
create mode 100644 src/views/helper/index.vue
create mode 100644 src/views/redirect/index.vue
create mode 100644 src/views/resetPassword/index.vue
create mode 100644 src/views/software/index.vue
create mode 100644 src/views/system/config/index.vue
create mode 100644 src/views/system/dict/index.vue
create mode 100644 src/views/system/log/index.vue
create mode 100644 src/views/system/menu/index.vue
create mode 100644 src/views/system/role/index.vue
create mode 100644 src/views/system/user/components/user-import.vue
create mode 100644 src/views/system/user/index.vue
create mode 100644 src/views/website/audition/draw.vue
create mode 100644 src/views/website/audition/realname.vue
create mode 100644 src/views/website/notices/index.vue
create mode 100644 src/views/website/question/index.vue
create mode 100644 src/views/website/statement/notes.vue
create mode 100644 src/views/website/statement/orders.vue
create mode 100644 src/views/website/statistics/index.vue
create mode 100644 src/views/website/styles/index.vue
create mode 100644 src/views/website/swVersions/index.vue
create mode 100644 tsconfig.json
create mode 100644 uno.config.ts
create mode 100644 vite.config.ts
diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..00ee2de
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,15 @@
+# http://editorconfig.org
+root = true
+
+# 表示所有文件适用
+[*]
+charset = utf-8 # 设置文件字符集为 utf-8
+end_of_line = lf # 控制换行类型(lf | cr | crlf)
+indent_style = space # 缩进风格(tab | space)
+indent_size = 2 # 缩进大小
+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..a0be9af
--- /dev/null
+++ b/.env.development
@@ -0,0 +1,11 @@
+# 应用端口
+VITE_APP_PORT = 3000
+
+# 代理前缀
+VITE_APP_BASE_API = '/dev-api'
+
+# 接口地址
+VITE_APP_API_URL = http://localhost:8989
+
+# 是否启用 Mock 服务
+VITE_MOCK_DEV_SERVER = false
diff --git a/.env.production b/.env.production
new file mode 100644
index 0000000..74d45c1
--- /dev/null
+++ b/.env.production
@@ -0,0 +1,3 @@
+# 代理前缀
+VITE_APP_BASE_API = '/prod-api'
+
diff --git a/.eslintignore b/.eslintignore
new file mode 100644
index 0000000..43af40f
--- /dev/null
+++ b/.eslintignore
@@ -0,0 +1,14 @@
+dist
+node_modules
+public
+.husky
+.vscode
+.idea
+*.sh
+*.md
+
+src/assets
+
+.eslintrc.cjs
+.prettierrc.cjs
+.stylelintrc.cjs
diff --git a/.eslintrc-auto-import.json b/.eslintrc-auto-import.json
new file mode 100644
index 0000000..adea0fa
--- /dev/null
+++ b/.eslintrc-auto-import.json
@@ -0,0 +1,309 @@
+{
+ "globals": {
+ "Component": true,
+ "ComponentPublicInstance": true,
+ "ComputedRef": true,
+ "EffectScope": true,
+ "ElMessage": true,
+ "ElMessageBox": true,
+ "ElNotification": true,
+ "InjectionKey": true,
+ "PropType": true,
+ "Ref": true,
+ "VNode": true,
+ "asyncComputed": true,
+ "autoResetRef": true,
+ "computed": true,
+ "computedAsync": true,
+ "computedEager": true,
+ "computedInject": true,
+ "computedWithControl": true,
+ "controlledComputed": true,
+ "controlledRef": true,
+ "createApp": true,
+ "createEventHook": true,
+ "createGlobalState": true,
+ "createInjectionState": true,
+ "createReactiveFn": true,
+ "createReusableTemplate": true,
+ "createSharedComposable": true,
+ "createTemplatePromise": true,
+ "createUnrefFn": true,
+ "customRef": true,
+ "debouncedRef": true,
+ "debouncedWatch": true,
+ "defineAsyncComponent": true,
+ "defineComponent": true,
+ "eagerComputed": true,
+ "effectScope": true,
+ "extendRef": true,
+ "getCurrentInstance": true,
+ "getCurrentScope": true,
+ "h": true,
+ "ignorableWatch": true,
+ "inject": true,
+ "isDefined": true,
+ "isProxy": true,
+ "isReactive": true,
+ "isReadonly": true,
+ "isRef": true,
+ "makeDestructurable": true,
+ "markRaw": true,
+ "nextTick": true,
+ "onActivated": true,
+ "onBeforeMount": true,
+ "onBeforeUnmount": true,
+ "onBeforeUpdate": true,
+ "onClickOutside": true,
+ "onDeactivated": true,
+ "onErrorCaptured": true,
+ "onKeyStroke": true,
+ "onLongPress": true,
+ "onMounted": true,
+ "onRenderTracked": true,
+ "onRenderTriggered": true,
+ "onScopeDispose": true,
+ "onServerPrefetch": true,
+ "onStartTyping": true,
+ "onUnmounted": true,
+ "onUpdated": true,
+ "pausableWatch": true,
+ "provide": true,
+ "reactify": true,
+ "reactifyObject": true,
+ "reactive": true,
+ "reactiveComputed": true,
+ "reactiveOmit": true,
+ "reactivePick": true,
+ "readonly": true,
+ "ref": true,
+ "refAutoReset": true,
+ "refDebounced": true,
+ "refDefault": true,
+ "refThrottled": true,
+ "refWithControl": true,
+ "resolveComponent": true,
+ "resolveRef": true,
+ "resolveUnref": true,
+ "shallowReactive": true,
+ "shallowReadonly": true,
+ "shallowRef": true,
+ "syncRef": true,
+ "syncRefs": true,
+ "templateRef": true,
+ "throttledRef": true,
+ "throttledWatch": true,
+ "toRaw": true,
+ "toReactive": true,
+ "toRef": true,
+ "toRefs": true,
+ "toValue": true,
+ "triggerRef": true,
+ "tryOnBeforeMount": true,
+ "tryOnBeforeUnmount": true,
+ "tryOnMounted": true,
+ "tryOnScopeDispose": true,
+ "tryOnUnmounted": true,
+ "unref": true,
+ "unrefElement": true,
+ "until": true,
+ "useActiveElement": true,
+ "useAnimate": true,
+ "useArrayDifference": true,
+ "useArrayEvery": true,
+ "useArrayFilter": true,
+ "useArrayFind": true,
+ "useArrayFindIndex": true,
+ "useArrayFindLast": true,
+ "useArrayIncludes": true,
+ "useArrayJoin": true,
+ "useArrayMap": true,
+ "useArrayReduce": true,
+ "useArraySome": true,
+ "useArrayUnique": true,
+ "useAsyncQueue": true,
+ "useAsyncState": true,
+ "useAttrs": true,
+ "useBase64": true,
+ "useBattery": true,
+ "useBluetooth": true,
+ "useBreakpoints": true,
+ "useBroadcastChannel": true,
+ "useBrowserLocation": true,
+ "useCached": true,
+ "useClipboard": true,
+ "useCloned": true,
+ "useColorMode": true,
+ "useConfirmDialog": true,
+ "useCounter": true,
+ "useCssModule": true,
+ "useCssVar": true,
+ "useCssVars": true,
+ "useCurrentElement": true,
+ "useCycleList": true,
+ "useDark": true,
+ "useDateFormat": true,
+ "useDebounce": true,
+ "useDebounceFn": true,
+ "useDebouncedRefHistory": true,
+ "useDeviceMotion": true,
+ "useDeviceOrientation": true,
+ "useDevicePixelRatio": true,
+ "useDevicesList": true,
+ "useDisplayMedia": true,
+ "useDocumentVisibility": true,
+ "useDraggable": true,
+ "useDropZone": true,
+ "useElementBounding": true,
+ "useElementByPoint": true,
+ "useElementHover": true,
+ "useElementSize": true,
+ "useElementVisibility": true,
+ "useEventBus": true,
+ "useEventListener": true,
+ "useEventSource": true,
+ "useEyeDropper": true,
+ "useFavicon": true,
+ "useFetch": true,
+ "useFileDialog": true,
+ "useFileSystemAccess": true,
+ "useFocus": true,
+ "useFocusWithin": true,
+ "useFps": true,
+ "useFullscreen": true,
+ "useGamepad": true,
+ "useGeolocation": true,
+ "useIdle": true,
+ "useImage": true,
+ "useInfiniteScroll": true,
+ "useIntersectionObserver": true,
+ "useInterval": true,
+ "useIntervalFn": true,
+ "useKeyModifier": true,
+ "useLastChanged": true,
+ "useLocalStorage": true,
+ "useMagicKeys": true,
+ "useManualRefHistory": true,
+ "useMediaControls": true,
+ "useMediaQuery": true,
+ "useMemoize": true,
+ "useMemory": true,
+ "useMounted": true,
+ "useMouse": true,
+ "useMouseInElement": true,
+ "useMousePressed": true,
+ "useMutationObserver": true,
+ "useNavigatorLanguage": true,
+ "useNetwork": true,
+ "useNow": true,
+ "useObjectUrl": true,
+ "useOffsetPagination": true,
+ "useOnline": true,
+ "usePageLeave": true,
+ "useParallax": true,
+ "useParentElement": true,
+ "usePerformanceObserver": true,
+ "usePermission": true,
+ "usePointer": true,
+ "usePointerLock": true,
+ "usePointerSwipe": true,
+ "usePreferredColorScheme": true,
+ "usePreferredContrast": true,
+ "usePreferredDark": true,
+ "usePreferredLanguages": true,
+ "usePreferredReducedMotion": true,
+ "usePrevious": true,
+ "useRafFn": true,
+ "useRefHistory": true,
+ "useResizeObserver": true,
+ "useScreenOrientation": true,
+ "useScreenSafeArea": true,
+ "useScriptTag": true,
+ "useScroll": true,
+ "useScrollLock": true,
+ "useSessionStorage": true,
+ "useShare": true,
+ "useSlots": true,
+ "useSorted": true,
+ "useSpeechRecognition": true,
+ "useSpeechSynthesis": true,
+ "useStepper": true,
+ "useStorage": true,
+ "useStorageAsync": true,
+ "useStyleTag": true,
+ "useSupported": true,
+ "useSwipe": true,
+ "useTemplateRefsList": true,
+ "useTextDirection": true,
+ "useTextSelection": true,
+ "useTextareaAutosize": true,
+ "useThrottle": true,
+ "useThrottleFn": true,
+ "useThrottledRefHistory": true,
+ "useTimeAgo": true,
+ "useTimeout": true,
+ "useTimeoutFn": true,
+ "useTimeoutPoll": true,
+ "useTimestamp": true,
+ "useTitle": true,
+ "useToNumber": true,
+ "useToString": true,
+ "useToggle": true,
+ "useTransition": true,
+ "useUrlSearchParams": true,
+ "useUserMedia": true,
+ "useVModel": true,
+ "useVModels": true,
+ "useVibrate": true,
+ "useVirtualList": true,
+ "useWakeLock": true,
+ "useWebNotification": true,
+ "useWebSocket": true,
+ "useWebWorker": true,
+ "useWebWorkerFn": true,
+ "useWindowFocus": true,
+ "useWindowScroll": true,
+ "useWindowSize": true,
+ "watch": true,
+ "watchArray": true,
+ "watchAtMost": true,
+ "watchDebounced": true,
+ "watchDeep": true,
+ "watchEffect": true,
+ "watchIgnorable": true,
+ "watchImmediate": true,
+ "watchOnce": true,
+ "watchPausable": true,
+ "watchPostEffect": true,
+ "watchSyncEffect": true,
+ "watchThrottled": true,
+ "watchTriggerable": true,
+ "watchWithFilter": true,
+ "whenever": true,
+ "ExtractDefaultPropTypes": true,
+ "ExtractPropTypes": true,
+ "ExtractPublicPropTypes": true,
+ "WritableComputedRef": true,
+ "acceptHMRUpdate": true,
+ "createPinia": true,
+ "defineStore": true,
+ "getActivePinia": true,
+ "injectLocal": true,
+ "mapActions": true,
+ "mapGetters": true,
+ "mapState": true,
+ "mapStores": true,
+ "mapWritableState": true,
+ "onBeforeRouteLeave": true,
+ "onBeforeRouteUpdate": true,
+ "provideLocal": true,
+ "setActivePinia": true,
+ "setMapStoreSuffix": true,
+ "storeToRefs": true,
+ "useClipboardItems": true,
+ "useI18n": true,
+ "useLink": true,
+ "useRoute": true,
+ "useRouter": true
+ }
+}
diff --git a/.eslintrc.cjs b/.eslintrc.cjs
new file mode 100644
index 0000000..8ae169a
--- /dev/null
+++ b/.eslintrc.cjs
@@ -0,0 +1,88 @@
+module.exports = {
+ root: true,
+ env: {
+ browser: true,
+ es2021: true,
+ node: true,
+ },
+ parser: "vue-eslint-parser",
+ extends: [
+ // https://eslint.vuejs.org/user-guide/#usage
+ "plugin:vue/vue3-recommended",
+ "./.eslintrc-auto-import.json",
+ "prettier",
+ "plugin:@typescript-eslint/recommended",
+ "plugin:prettier/recommended",
+ ],
+ parserOptions: {
+ ecmaVersion: "latest",
+ sourceType: "module",
+ parser: "@typescript-eslint/parser",
+ project: "./tsconfig.*?.json",
+ createDefaultProgram: false,
+ extraFileExtensions: [".vue"],
+ },
+ plugins: ["vue", "@typescript-eslint"],
+ rules: {
+ // https://eslint.vuejs.org/rules/#priority-a-essential-error-prevention
+ "vue/multi-word-component-names": "off",
+ "vue/no-v-model-argument": "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",
+ },
+ ],
+
+ "@typescript-eslint/no-empty-function": "off", // 关闭空方法检查
+ "@typescript-eslint/no-explicit-any": "off", // 关闭any类型的警告
+ "@typescript-eslint/no-non-null-assertion": "off",
+ "@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",
+ "@typescript-eslint/no-unused-vars": "off",
+
+ "prettier/prettier": [
+ "error",
+ {
+ useTabs: false, // 不使用制表符
+ },
+ ],
+ },
+ // eslint不能对html文件生效
+ overrides: [
+ {
+ files: ["*.html"],
+ processor: "vue/.vue",
+ },
+ ],
+ // https://eslint.org/docs/latest/use/configure/language-options#specifying-globals
+ globals: {
+ OptionType: "readonly",
+ },
+};
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..fee6999
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,18 @@
+node_modules
+.DS_Store
+dist
+dist-ssr
+*.local
+.history
+
+# Editor directories and files
+.idea
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.local
+
+package-lock.json
+pnpm-lock.yaml
+stats.html
diff --git a/.hintrc b/.hintrc
new file mode 100644
index 0000000..8cc5c90
--- /dev/null
+++ b/.hintrc
@@ -0,0 +1,15 @@
+{
+ "extends": [
+ "development"
+ ],
+ "hints": {
+ "compat-api/css": [
+ "default",
+ {
+ "ignore": [
+ "text-size-adjust"
+ ]
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/.husky/commit-msg b/.husky/commit-msg
new file mode 100644
index 0000000..fd2bf70
--- /dev/null
+++ b/.husky/commit-msg
@@ -0,0 +1 @@
+npx --no-install commitlint --edit $1
diff --git a/.husky/pre-commit b/.husky/pre-commit
new file mode 100644
index 0000000..b18d041
--- /dev/null
+++ b/.husky/pre-commit
@@ -0,0 +1 @@
+npm run lint:lint-staged
diff --git a/.prettierignore b/.prettierignore
new file mode 100644
index 0000000..f3e9850
--- /dev/null
+++ b/.prettierignore
@@ -0,0 +1,11 @@
+dist
+node_modules
+public
+.husky
+.vscode
+.idea
+*.sh
+*.md
+
+src/assets
+stats.html
diff --git a/.prettierrc.cjs b/.prettierrc.cjs
new file mode 100644
index 0000000..7ce60da
--- /dev/null
+++ b/.prettierrc.cjs
@@ -0,0 +1,46 @@
+module.exports = {
+ // (x)=>{},单个参数箭头函数是否显示小括号。(always:始终显示;avoid:省略括号。默认:always)
+ arrowParens: "always",
+ // 开始标签的右尖括号是否跟随在最后一行属性末尾,默认false
+ bracketSameLine: false,
+ // 对象字面量的括号之间打印空格 (true - Example: { foo: bar } ; false - Example: {foo:bar})
+ bracketSpacing: true,
+ // 是否格式化一些文件中被嵌入的代码片段的风格(auto|off;默认auto)
+ embeddedLanguageFormatting: "auto",
+ // 指定 HTML 文件的空格敏感度 (css|strict|ignore;默认css)
+ htmlWhitespaceSensitivity: "ignore",
+ // 当文件已经被 Prettier 格式化之后,是否会在文件顶部插入一个特殊的 @format 标记,默认false
+ insertPragma: false,
+ // 在 JSX 中使用单引号替代双引号,默认false
+ jsxSingleQuote: false,
+ // 每行最多字符数量,超出换行(默认80)
+ printWidth: 120,
+ // 超出打印宽度 (always | never | preserve )
+ proseWrap: "preserve",
+ // 对象属性是否使用引号(as-needed | consistent | preserve;默认as-needed:对象的属性需要加引号才添加;)
+ quoteProps: "as-needed",
+ // 是否只格式化在文件顶部包含特定注释(@prettier| @format)的文件,默认false
+ requirePragma: false,
+ // 结尾添加分号
+ semi: true,
+ // 使用单引号 (true:单引号;false:双引号)
+ singleQuote: false,
+ // 缩进空格数,默认2个空格
+ tabWidth: 2,
+ // 元素末尾是否加逗号,默认es5: ES5中的 objects, arrays 等会添加逗号,TypeScript 中的 type 后不加逗号
+ trailingComma: "es5",
+ // 指定缩进方式,空格或tab,默认false,即使用空格
+ useTabs: false,
+ // vue 文件中是否缩进 ",
+ ""
+ ],
+ "description": "Vue3.0"
+ }
+}
diff --git a/.vscode/vue3.2.code-snippets b/.vscode/vue3.2.code-snippets
new file mode 100644
index 0000000..a083940
--- /dev/null
+++ b/.vscode/vue3.2.code-snippets
@@ -0,0 +1,17 @@
+{
+ "Vue3.2+快速生成模板": {
+ "scope": "vue",
+ "prefix": "Vue3.2+",
+ "body": [
+ "",
+ "",
+ "",
+ "
6t^5S;9CdJb`A0ak_#-&X{{Yr=YGB{&YH(Qa4t)7O zLzq%c|1qQ6Z*A5_99=S>Q)cQ^X3|&uDKYSmG%4~Lq*kxgrnV|M(%EQ5Fgod^v4n5E zBOAT-sdJ3Mo4lBHA74bPe`$+QsPD(Q?NG1;?sW=(0$+hT@Zv!qSn&}Kv%QByOWq^r z8n9-q2CLa`!FFCXxO3J*=$hKm*e$PHT=X(iCHPeI7tLEv`ph5F5Bwv(-(DlWpebrf zWjlVL>aedM#c%V)nc-XRaYqTrA@fTo7iJ2Z;M0Z-@OT1{juw)NFDg{BY*BX zaO0>2=Vc$@;G*|nKfeZSX#C%x4sXF}=?4gs_zZ~~Kll4?xO_!dezz4byBHsSf~-&d zsWCu!ep{q?G%0fxUn<3-hJr+(ob@u8{nnRq9M!t37NqgmGD!JFXrN5>*#PmHTRuWH zFTHqcKDw=_X>wwF*L865yMBiS)x)-P-@?8*ZxC-`Kl+2O;AhMs&0}GPl@AUWMtLiX z8j^X%G@N77<66YGCj6=A!W{CHiJ}K})d46q{+*Q1hRgI`T7`_BszuB`YByMYmF{x+ z$ljOtmVL1Gh}6Tw9wJX-T=}1!cj9_}`w-j9m-`pLs RoQxT%NQ388ieW4DKo=-W zrLakd ORK@t1oDs*_ p?yPl3O;h i<~&-|F%6{HFpx75J&ZPX+#b1#nF9&&mi|seliC ztvm3X0nf{@CS#JXwb#TssYzcoQIC;RJpZ;PuOrw0oSI@7x97iW+W%%rEMoB@|NgC} z^P-(nUu)VK*$XG-+uC#dGWGX0OWF82)@9@YmI>CsscF`HRrR;^SGB*^ P ;{X5v literal 0 HcmV?d00001 diff --git a/public/html/coin.html b/public/html/coin.html new file mode 100644 index 0000000..fd3c34b --- /dev/null +++ b/public/html/coin.html @@ -0,0 +1,66 @@ + + + ++ + + diff --git a/public/html/contact.html b/public/html/contact.html new file mode 100644 index 0000000..0593d4d --- /dev/null +++ b/public/html/contact.html @@ -0,0 +1,23 @@ + + +唱作音符+ ++ ++ ++ 唱作音符是唱作网的操作度量工具,在使用唱作魔方软件时会用到唱作音符。唱作音符通常叫作“音符”。 ++++ +音符使用:++ 在唱作魔方软件中:+
+ (1)保存音乐 (-1)
+ (2)保存音乐时使用扩展音色库 (-80)
+ (3)保存音乐时使用收费风格
+ (4)其它 +++ +用户获取:++ (1)在注册用户时唱作网会赠予一定的音符+
+ (2)充值兑换
+++ +音符充值:++ 进入账户管理页,选择 "唱作音符" 下的 "充值提现"+
+ 当前兑换比例:¥1元 = 100音符 +++ +音符提现:++ 进入账户管理页,选择 "唱作音符" 下的 "充值提现"+
+ 最低提现金额为100元(即10000音符);唱作网将收取按提现金额6%的音符作为平台管理费,提现后24小时内到账 +++ +查看明细:++ 进入账户管理页,选择 "唱作音符" 下的 "音符明细" 查看+
+++ + + ++ 注:音符获取细则和使用细则等请以唱作网具体规定为准+
+++ + + diff --git a/public/html/help.css b/public/html/help.css new file mode 100644 index 0000000..2babfca --- /dev/null +++ b/public/html/help.css @@ -0,0 +1,15 @@ +@charset "utf-8"; + +/*帮助内容*/ +.helpContent_border{width:100%; margin:0 0 30px 0px;} +.helpContent_border .helpContent_title{width:100%; padding: 20px 0 10px 0; text-align:center; font-size:20px; font-weight:bold;} +.helpContent_border .content{width:100%; padding:25px 0 0 0;} +.helpContent_border .content .title{font-size:16px; font-weight:bold;padding-left: 10px;} +.helpContent_border .content .msg{padding:10px 0 0 20px; font-size:12px; line-height:24px;} +.helpContent_border .content .img_border{width:100%; padding:20px 0 20px 0; text-align:center;} +.helpContent_border .content .img_border img{max-width:850px;} +table, th, td { + border: 1px solid black; + border-collapse: collapse; + text-align: center; +} diff --git a/public/html/privacy.html b/public/html/privacy.html new file mode 100644 index 0000000..1fcee3f --- /dev/null +++ b/public/html/privacy.html @@ -0,0 +1,156 @@ + + +联系我们+ ++ ++ + + +++
+
+ 邮箱:music@ichangzuo.com +
+
+ QQ群:271573952 +++ + + diff --git a/public/html/user.html b/public/html/user.html new file mode 100644 index 0000000..dd514e1 --- /dev/null +++ b/public/html/user.html @@ -0,0 +1,120 @@ + + +唱作网隐私政策+ ++ ++ ++ 欢迎您使用唱作网产品及服务!+
+ 我们非常重视保护您的个人信息和隐私。您可以通过《唱作网隐私政策》(以下简称“隐私政策”)了解我们收集、使用、存储用户个人信息的情况,以及您所享有的相关权利。请您仔细阅读并充分理解相关内容:
+ 1、为向您提供产品及服务,我们将依据隐私政策收集、使用、存储必要的信息。
+ 2、基于您的明示授权,我们可能会申请开启您的存储、网络、麦克风等设备权限,您有权拒绝或取消授权。
+ 3、您可以访问、更正、删除您的个人信息,还可以撤回授权同意、注销账号、投诉举报以及调整其他隐私设置。
+ 4、我们已采取符合业界标准的安全防护措施保护您的个人信息。
+ 5、如您是未成年人,请您和您的监护人仔细阅读本隐私政策,并在征得您的监护人授权同意的前提下使用我们的服务或向我们提供个人信息。
+ 请您阅读完整版《唱作网用户协议》及本隐私政策了解详细信息。
+++ +一、 我们如何收集和使用您的个人信息+++1、完成注册
+ 注册账号时,我们会要求您提供相应的个人信息,包括您的账号、密码、邮箱、手机号码等。
+2、使用产品
+ (1)我们会收集您在使用我们的产品和服务时设备的相关信息,例如设备类型、操作系统类型及版本、浏览器类型和版本、屏幕分辨率、IP地址等,以及因产品而异的其他技术信息。
+ (2)在您使用我们的产品或服务,以及与我们互动时由您直接提交给我们的信息,包括您输入的信息或您为了获得客服支持而提供的问题或信息等。
+ (3)当您使用我们的产品和服务时,我们会自动收集并存储必要的日志信息,如服务的每次访问时间、访问的页面路径、客户端 IP地址、事件信息(如错误、崩溃、重启、升级)等。 +3、实名认证
+ 当您使用我们的部分产品与/或服务时,根据相关法律法规要求,需要您进行实名认证。实名认证需要上传实名认证信息。不同的实名认证主体类型会要求不同实名认证信息,这些信息包括:姓名、证件号码、公司名称、公司统一信用代码、学生证信息、身份证信息等。
+ 上述信息将仅在您使用我们的产品与/或服务期间持续授权我们保存使用。在您主动注销账号时,我们将根据适用法律法规的要求尽快使其匿名或删除您的个人信息。 +4、充值提现
+ (1)您可以通过微信支付、支付宝支付等进行充值。支付功能本身并不收集您的个人信息,但我们需要将您的订单号与交易金额信息与这些支付机构共享以实现其确认您的支付指令并完成支付。
+ (2)为充分保障您的合法权益,我们允许您将账户余额提现。在此过程中,您至少需要向我们提供微信账号、支付宝账号、或汇款银行名称、汇款账号、汇款账户名、汇款金额等信息。 +++ +二、设备权限调用++ 在您使用我们的产品及服务过程中,我们需要在必要范围内向您申请获取设备权限。请您知悉,我们不会默认开启您设备的权限,仅在您主动确认开启的情况下,我们才有可能通过设备权限收集您的信息。+
+ 我们的产品及服务调用的权限、调用权限的目的,以及调用权限前向您询问的情况请见下表: ++ +
++ + + +设备权限 +调用权限的目的 +是否询问 +可否关闭 ++ +网络 +访问网络 +是 +可 ++ +外部存储 +存储应用运行所需文件 +是 +不可 ++ +麦克风 +录音 +是 +可 ++ + +系统设置 +设置铃音 +是 +可 +++ +三、我们如何使用您的个人信息++ (1)我们会根据本政策的约定并为实现我们的服务的目的对所收集的个人信息进行使用。+
+ (2)请您注意,您在使用我们提供的服务时所提供的所有个人信息,除非您删除或通过系统设置拒绝我们收集,否则将在您使用我们的服务期间持续授权我们使用。在您注销账号时,我们将停止使用并删除您的个人信息。
+ (3)我们会对我们提供的服务使用情况进行统计,并可能会与公众或第三方共享这些统计信息,以用于产品开发、服务优化、安全保障的目的。但这些统计信息不包含您的任何身份识别信息。
+ (4)当我们要将您的个人信息用于本政策未载明的其它用途时,或基于特定目的收集而来的信息用于其他目的时,会通过您主动做出勾选的形式事先征求您的同意。 +++ +四、我们如何使用Cookie和同类技术++ (1)为确保网站正常运转,我们有时会在计算机或移动设备上存储名为 Cookie 的小数据文件。+
+ (2)我们启用Cookie的目的与大多数网站的目的一样,即改善用户体验。借助于 Cookie,网站能够记住用户的单次访问(使用会话 Cookie)或多次访问(使用永久 Cookie)。
+ 借助于 Cookie,网站能够保存设置,例如计算机或移动设备的语言、字体大小和其他浏览偏好。这意味着,用户无需在每次访问时重新配置用户偏好设置。
+ 如果某个网站不使用 Cookie,那么在用户每一次打开网页时,该网站都会将其视为新访客。例如,如果您登录某个网站后转到另一个网页,该网站就不会识别出您,而您会被再次注销。
+ (3)我们不会将 Cookie 用于本政策所述目的之外的任何用途。
+ (4)您可根据自己的偏好管理或删除 Cookie。您可以清除计算机上保存的所有 Cookie,大部分网络浏览器都设有阻止 Cookie 的功能。但如果您这么做,则需要在每一次访问我们的网站时亲自更改用户设置。 +++ +五、我们如何披露您的个人信息++ 通常我们不会对外披露您的个人信息,但以下场景除外:+
+ (1)在某些服务由我们的授权合作伙伴提供的情况下,我们会如本政策描述与该合作伙伴共享您的个人信息。例如,委托合作伙伴代表我们处理热线、发送电子邮件、提供技术支持等,我们会要求合作伙伴仅能将您的个人信息用于代表我们向您提供服务。
+ (2)在适用的法律要求或响应法律程序的情况下,我们也可能会向相关的执法机关或者其他政府机关披露您的个人信息。在某些管辖区,如果我们牵涉到重组、合并或破产和清理诉讼,那么您的个人信息还可能会被披露给交易方。
+ (3)我们还会在合理的情况下披露您的数据,例如出于执行合同以及我们认为为阻止身体损害或财产损失或调查可能的或实际的非法行为有必要披露且披露是适当的。 +++ +六、我们如何保护和留存您的个人信息++ (1)我们重视个人信息的安全,采用适当的物理、管理和技术保障措施来保护您的个人信息不被未经授权访问、披露、使用、修改、损坏或丢失。+
+ 例如,我们会使用加密技术确保数据的机密性;我们会使用保护机制防止数据遭到恶意攻击;我们会部署访问控制机制,确保只有授权人员才可访问个人信息;以及我们会举办安全和隐私保护培训课程,加强员工对于保护个人信息重要性的认识。
+ 我们会尽力保护您的个人信息,但是请注意任何安全措施都无法做到无懈可击。
+ (2)我们将会在达成本政策所述目的所需的期限内保留您的个人信息,除非按照法律要求或许可需要延长保留期或受到法律的允许。因为基于不同的场景和产品及服务的不同,数据的存储期可能会有所不同。
+ 我们用于确定存留期的标准包括:完成该业务目的需要留存个人信息的时间,包括提供产品和服务,维护相应的交易及业务记录,管控并提升产品与服务性能与质量,保证产品和服务的安全,应对可能的用户查询或投诉,问题定位等;用户是否同意更长的留存期间;法律、合同等是否有保留数据的特殊要求等。
+ 只要您的账户是为您提供服务必须,我们都将保留您的注册信息。您也可以选择注销您的账号,在您注销账号后,我们会停止基于该账号提供产品和服务,并在无特殊法律要求的情况下,删除您相应的个人信息或对其进行匿名化处理。 +++ +七、我们如何保护儿童的个人信息++ (1)我们的产品和服务主要面向成人。如果没有父母或监护人的同意,(未满14周岁的未成年人)不得创建自己的用户帐户。+
+ (2)对于经父母同意而收集儿童个人信息的情况,我们只会在受到法律允许、父母或监护人明确同意或者保护儿童所必要的情况下使用或披露此数据。
+ (3)如果我们发现在未事先获得可证实的父母同意的情况下收集了儿童的个人信息,则会设法尽快删除相关数据。 +++ +八、本政策如何更新++ 我们保留不时更新或修改本政策的权利。如果我们的隐私政策变更,我们会将最新版隐私政策发布在这里。+
+ 如果我们对隐私政策做出了重大变更,我们还可能会通过不同渠道向您发送变更通知,例如,在我们的网站上发布通知或者向您发布单独的通知。 +++ + + +九、其他++ (1)本政策的订立、执行和解释及争议的解决均应适用中国法律。+
+ (2)如双方就本协议内容或其执行发生任何争议,双方应尽量友好协商解决;协商不成时,任何一方均可向唱作网所在地的人民法院提起诉讼。 +++ + + diff --git a/public/html/vip.html b/public/html/vip.html new file mode 100644 index 0000000..488a64f --- /dev/null +++ b/public/html/vip.html @@ -0,0 +1,33 @@ + + +唱作网用户协议+ ++ ++ ++ 欢迎您使用唱作网产品及服务!+
+ 为使用唱作网产品及服务(以下统称“本产品及服务”),您应当阅读并遵守《唱作网用户协议》(以下简称“本协议”),以及《唱作网隐私政策》。
+ 在您注册成为唱作网用户的过程中,您需要完成我们的注册流程并通过点击同意的形式在线签署以下使用协议,请务必仔细阅读,充分理解协议中的条款后再点击同意,这些条款可能会明确您应履行的义务或对您的权利有所限制。 +++ +服务内容++ (1)本产品及服务的具体内容由唱作网根据实际情况提供,例如账户管理、软件升级等。唱作网保留随时变更、中断或终止部分或全部产品及服务的权利。+
+ (2)当您使用本产品时,您应选择与您的终端、系统等相匹配的本产品版本,否则,您可能无法正常使用本产品。 + (3)唱作网在提供产品及服务时,可能会对部分产品及服务收取一定的费用。在此情况下, 唱作网会在相关页面上做明确的提示。如用户拒绝支付该等费用,则不能使用相关产品及服务。
+ (4)唱作网仅提供相关的产品及服务,除此之外与之有关的设备(如电脑、移动设备、调制解调器及其他与接入互联网有关的装置)及所需的费用( 如为接入互联网而支付的电话费及上网费 )均应由用户自行负担。 +++ +使用规则++ (1)当您注册成功后,唱作网将给予您一个用户帐号及相应的密码,该用户帐号和密码由您负责保管,您应当对以其用户帐号进行的所有活动和事件负法律责任。+
+ (2)在您使用本产品与服务视为同意接受唱作网通过电子邮件或其它方式向用户发送的商品促销或其他相关商业信息。
+ (3)您在使用本服务过程中,必须遵循以下原则:
+ A:遵守中国有关的法律和法规;
+ B:不得为任何非法目的而使用网络服务系统;
+ C:遵守所有与本产品及服务有关的网络协议、规定和程序;
+ D:不得利用本产品及服务进行任何可能对互联网的正常运转造成不利影响的行为;
+ E:不得利用本产品及服务传播任何骚扰性的、中伤他人的、辱骂性的、恐吓性的、庸俗淫秽的或其他任何非法的信息资料;
+ F:不得利用本产品及服务进行任何不利于唱作网的行为;
+ G:如发现任何非法使用用户帐号或帐号出现安全漏洞的情况,应立即通告唱作网。 +++ +内容所有权++ (1)唱作网提供的网络服务内容可能包括:文字、软件、声音、图片、MV、图表等。所有这些内容受版权、商标和其它财产所有权法律的保护。+
+ (2)您只有在获得唱作网或其他相关权利人的授权之后才能使用这些内容,而不能擅自复制、再造这些内容、或创造与内容有关的派生产品。
+ (3)您使用本产品及服务创作或制作的歌曲,著作权仍归您所有。唱作网对您著作权部分不作任何要求。
+++ +隐私保护++ 隐私保护相关条款以《唱作网隐私政策》内容为准。 ++++ +免责声明++ (1)您明确同意其使用本产品及服务所存在的风险将完全由其您承担,因您使用本产品及服务而产生的一切后果也由您承担, 唱作网对此不承担任何责任。+
+ (2)唱作网不担保本产品及服务一定能满足您的要求,也不担保本产品及服务不会中断,对本产品及服务的及时性、安全性、准确性也都不作担保。
+++ +服务变更、中断或终止++ (1)如因系统维护或升级的需要而需暂停网络服务, 唱作网将尽可能事先进行通告。+
+ (2)如发生下列任何一种情形, 唱作网有权随时中断或终止向您提供本协议中的服务而无需通知:
+ A:您提供的个人资料不真实;
+ B:您违反本协议中规定的使用规则。
+ (3)除前款所述情形外, 唱作网同时保留在不事先通知您的情况下随时中断或终止部分或全部产品及服务的权利,对于所有服务的中断或终止而造成的任何损失, 唱作网无须承担责任。 +++ +违约赔偿++ 您同意保障和维护唱作网及其他用户的利益,如因您违反有关法律、法规或本协议项下的任何条款而给唱作网或任何其他第三人造成损失,您同意承担由此造成的损害赔偿责任。 ++++ +修改协议++ (1)唱作网将可能不时的修改本协议的有关条款,一旦条款内容发生变动,唱作网将尽量在相关页面提示修改内容。+
+ (2)如果不同意唱作网对服务条款所做的修改,您有权停止使用本产品及服务。如果您继续使用本产品及服务,则视为您接受服务条款的变动。 +++ +法律管辖++ (1)本协议的订立、执行和解释及争议的解决均应适用中国法律。+
+ (2)如双方就本协议内容或其执行发生任何争议,双方应尽量友好协商解决;协商不成时,任何一方均可向唱作网所在地的人民法院提起诉讼。 +++ +通知和送达++ 本协议项下所有的通知均可通过重要页面公告、电子邮件或常规的信件传送等方式进行;该等通知于发送之日视为已送达收件人。 ++++ + + +其他规定++ (1)本协议构成双方对本协议之约定事项及其他有关事宜的完整协议,除本协议规定的之外,未赋予本协议各方其他权利。+
+ (2)如本协议中的任何条款无论因何种原因完全或部分无效或不具有执行力,本协议的其余条款仍应有效并且有约束力。
+ (3)本协议中的标题仅为方便而设,在解释本协议时应被忽略。 +++ + + diff --git a/src/App.vue b/src/App.vue new file mode 100644 index 0000000..c2ad224 --- /dev/null +++ b/src/App.vue @@ -0,0 +1,24 @@ + +VIP会员+ +++ +特权:++ (1)唱作魔方所有版本免收功能费;+
+ (2)唱作魔方所有版本使用收费风格时享受8折优惠;
+ (3)唱作魔方所有版本可使用离线保存功能;
+
+ 更多VIP会员特权敬请期待! +++ + + +费用标准:++ (1)一月:1000 音符+
+ (2)半年:5500 音符
+ (3)一年:10000 音符
+ (4)两年:20000 音符
+(5)终身:30000 音符(为庆祝唱作网首次推出VIP会员服务,限时可成为终身会员。目前已结束。)++ + + + diff --git a/src/api/auth.ts b/src/api/auth.ts new file mode 100644 index 0000000..f28b5bf --- /dev/null +++ b/src/api/auth.ts @@ -0,0 +1,150 @@ +import request from "@/utils/request"; +import { verify } from "crypto"; + +const AUTH_BASE_URL = "/api/v1/auth"; + +class AuthAPI { + /** 登录 接口*/ + static login(data: LoginData) { + const formData = new FormData(); + formData.append("username", data.username); + formData.append("password", data.password); + formData.append("captchaKey", data.captchaKey); + formData.append("captchaCode", data.captchaCode); + + return request+ ({ + url: `${AUTH_BASE_URL}/login`, + method: "post", + data: formData, + headers: { + "Content-Type": "multipart/form-data", + }, + }); + } + + /** 注销 接口*/ + static logout() { + return request({ + url: `${AUTH_BASE_URL}/logout`, + method: "delete", + }); + } + + /** 获取验证码 接口*/ + static getCaptcha() { + return request ({ + url: `${AUTH_BASE_URL}/captcha`, + method: "get", + }); + } + + static sendCode(data: SendCodeData) { + const formData = new FormData(); + formData.append("contact", data.contact); + formData.append("captchaKey", data.captchaKey); + formData.append("captchaCode", data.captchaCode); + + return request({ + url: `${AUTH_BASE_URL}/sendRegCode`, + method: "post", + data: formData, + headers: { + "Content-Type": "multipart/form-data", + }, + }); + } + + /** 登录 接口*/ + static register(data: RegisterData) { + const formData = new FormData(); + formData.append("username", data.username); + formData.append("password", data.password); + formData.append("verifyCode", data.verifyCode); + + return request ({ + url: `${AUTH_BASE_URL}/register`, + method: "post", + data: formData, + headers: { + "Content-Type": "multipart/form-data", + }, + }); + } + + static autoLogin(username: string, password: string) { + const formData = new FormData(); + formData.append("username", username); + formData.append("password", password); + + return request ({ + url: `${AUTH_BASE_URL}/autoLogin`, + method: "post", + data: formData, + headers: { + "Content-Type": "multipart/form-data", + }, + }); + } +} + +export default AuthAPI; + +/** 登录请求参数 */ +export interface LoginData { + /** 用户名 */ + username: string; + /** 密码 */ + password: string; + /** 验证码缓存key */ + captchaKey: string; + /** 验证码 */ + captchaCode: string; +} + +/** 登录响应 */ +export interface LoginResult { + /** 访问token */ + accessToken?: string; + /** 过期时间(单位:毫秒) */ + expires?: number; + /** 刷新token */ + refreshToken?: string; + /** token 类型 */ + tokenType?: string; +} + +/** 验证码响应 */ +export interface CaptchaResult { + /** 验证码缓存key */ + captchaKey: string; + /** 验证码图片Base64字符串 */ + captchaBase64: string; +} + +export interface CaptchaData { + /** 验证码缓存key */ + captchaKey: string; + /** 验证码 */ + captchaCode: string; +} + +export interface SendCodeData { + /** 发送验证码账号 */ + contact: string; + /** 验证码缓存key */ + captchaKey: string; + /** 验证码 */ + captchaCode: string; +} + +/** 注册请求参数 */ +export interface RegisterData { + /** 用户名 */ + username: string; + /** 密码 */ + password: string; + /** 重复输入密码 */ + repeatPassword: string; + /** 验证码 */ + verifyCode: string; +} diff --git a/src/api/bank.ts b/src/api/bank.ts new file mode 100644 index 0000000..19b2260 --- /dev/null +++ b/src/api/bank.ts @@ -0,0 +1,28 @@ +import request from "@/utils/request"; + +const BANK_BASE_URL = "/api/v1/bank"; + +class BankAPI { + static hotlist() { + return request ({ + url: `${BANK_BASE_URL}/hotList`, + method: "get", + }); + } + + static bankInfo() { + return request ({ + url: `${BANK_BASE_URL}/me`, + method: "get", + }); + } +} + +export default BankAPI; + +export interface BankInfo { + userId: number; + bankName?: string; + bankCardNum?: string; + bankCardName?: string; +} diff --git a/src/api/codegen.ts b/src/api/codegen.ts new file mode 100644 index 0000000..166aa22 --- /dev/null +++ b/src/api/codegen.ts @@ -0,0 +1,191 @@ +import request from "@/utils/request"; + +const GENERATOR_BASE_URL = "/api/v1/codegen"; + +class GeneratorAPI { + /** 获取数据表分页列表 */ + static getTablePage(params: TablePageQuery) { + return request >({ + url: `${GENERATOR_BASE_URL}/table/page`, + method: "get", + params: params, + }); + } + + /** 获取代码生成配置 */ + static getGenConfig(tableName: string) { + return request ({ + url: `${GENERATOR_BASE_URL}/${tableName}/config`, + method: "get", + }); + } + + /** 获取代码生成配置 */ + static saveGenConfig(tableName: string, data: GenConfigForm) { + return request({ + url: `${GENERATOR_BASE_URL}/${tableName}/config`, + method: "post", + data: data, + }); + } + + /** 获取代码生成预览数据 */ + static getPreviewData(tableName: string) { + return request ({ + url: `${GENERATOR_BASE_URL}/${tableName}/preview`, + method: "get", + }); + } + + /** 重置代码生成配置 */ + static resetGenConfig(tableName: string) { + return request({ + url: `${GENERATOR_BASE_URL}/${tableName}/config`, + method: "delete", + }); + } + + /** + * 下载 ZIP 文件 + * @param url + * @param fileName + */ + static download(tableName: string) { + return request({ + url: `${GENERATOR_BASE_URL}/${tableName}/download`, + method: "get", + responseType: "blob", + }).then((response) => { + const fileName = decodeURI( + response.headers["content-disposition"].split(";")[1].split("=")[1] + ); + + const blob = new Blob([response.data], { type: "application/zip" }); + const a = document.createElement("a"); + const url = window.URL.createObjectURL(blob); + a.href = url; + a.download = fileName; + a.click(); + window.URL.revokeObjectURL(url); + }); + } +} + +export default GeneratorAPI; + +/** 代码生成预览对象 */ +export interface GeneratorPreviewVO { + /** 文件生成路径 */ + path: string; + /** 文件名称 */ + fileName: string; + /** 文件内容 */ + content: string; +} + +/** 数据表分页查询参数 */ +export interface TablePageQuery extends PageQuery { + /** 关键字(表名) */ + keywords?: string; +} + +/** 数据表分页对象 */ +export interface TablePageVO { + /** 表名称 */ + tableName: string; + + /** 表描述 */ + tableComment: string; + + /** 存储引擎 */ + engine: string; + + /** 字符集排序规则 */ + tableCollation: string; + + /** 创建时间 */ + createTime: string; +} + +/** 代码生成配置表单 */ +export interface GenConfigForm { + /** 主键 */ + id?: number; + + /** 表名 */ + tableName?: string; + + /** 业务名 */ + businessName?: string; + + /** 模块名 */ + moduleName?: string; + + /** 包名 */ + packageName?: string; + + /** 实体名 */ + entityName?: string; + + /** 作者 */ + author?: string; + + /** 上级菜单 */ + parentMenuId?: number; + + /** 后端应用名 */ + backendAppName?: string; + /** 前端应用名 */ + frontendAppName?: string; + + /** 字段配置列表 */ + fieldConfigs?: FieldConfig[]; +} + +/** 字段配置 */ +export interface FieldConfig { + /** 主键 */ + id?: number; + + /** 列名 */ + columnName?: string; + + /** 列类型 */ + columnType?: string; + + /** 字段名 */ + fieldName?: string; + + /** 字段类型 */ + fieldType?: string; + + /** 字段描述 */ + fieldComment?: string; + + /** 是否在列表显示 */ + isShowInList?: number; + + /** 是否在表单显示 */ + isShowInForm?: number; + + /** 是否在查询条件显示 */ + isShowInQuery?: number; + + /** 是否必填 */ + isRequired?: number; + + /** 表单类型 */ + formType?: number; + + /** 查询类型 */ + queryType?: number; + + /** 字段长度 */ + maxLength?: number; + + /** 字段排序 */ + fieldSort?: number; + + /** 字典类型 */ + dictType?: string; +} diff --git a/src/api/config.ts b/src/api/config.ts new file mode 100644 index 0000000..72760d7 --- /dev/null +++ b/src/api/config.ts @@ -0,0 +1,104 @@ +import request from "@/utils/request"; + +const CONFIG_BASE_URL = "/api/v1/config"; + +class ConfigAPI { + /** 获取系统配置分页数据 */ + static getPage(queryParams?: ConfigPageQuery) { + return request >({ + url: `${CONFIG_BASE_URL}/page`, + method: "get", + params: queryParams, + }); + } + /** + * 获取系统配置表单数据 + * + * @param id ConfigID + * @returns Config表单数据 + */ + static getFormData(id: number) { + return request ({ + url: `${CONFIG_BASE_URL}/${id}/form`, + method: "get", + }); + } + + /** 添加系统配置*/ + static add(data: ConfigForm) { + return request({ + url: `${CONFIG_BASE_URL}`, + method: "post", + data: data, + }); + } + + /** + * 更新系统配置 + * + * @param id ConfigID + * @param data Config表单数据 + */ + static update(id: number, data: ConfigForm) { + return request({ + url: `${CONFIG_BASE_URL}/${id}`, + method: "put", + data: data, + }); + } + + /** + * 删除系统配置 + * + * @param ids 系统配置ID + */ + static deleteById(id: number) { + return request({ + url: `${CONFIG_BASE_URL}/${id}`, + method: "delete", + }); + } + + static refreshCache() { + return request({ + url: `${CONFIG_BASE_URL}`, + method: "patch", + }); + } +} + +export default ConfigAPI; + +/** $系统配置分页查询参数 */ +export interface ConfigPageQuery extends PageQuery { + /** 搜索关键字 */ + keywords?: string; +} + +/** 系统配置表单对象 */ +export interface ConfigForm { + /** 主键 */ + id?: number; + /** 配置名称 */ + configName?: string; + /** 配置键 */ + configKey?: string; + /** 配置值 */ + configValue?: string; + /** 描述、备注 */ + remark?: string; +} + +/** 系统配置分页对象 */ +export interface ConfigPageVO { + /** 主键 */ + id?: number; + /** 配置名称 */ + configName?: string; + /** 配置键 */ + configKey?: string; + /** 配置值 */ + configValue?: string; + /** 描述、备注 */ + remark?: string; +} diff --git a/src/api/dict.ts b/src/api/dict.ts new file mode 100644 index 0000000..83cd675 --- /dev/null +++ b/src/api/dict.ts @@ -0,0 +1,192 @@ +import request from "@/utils/request"; + +const DICT_BASE_URL = "/api/v1/dict"; + +class DictAPI { + /** + * 获取字典分页列表 + * + * @param queryParams 查询参数 + * @returns 字典分页结果 + */ + static getPage(queryParams: DictPageQuery) { + return request >({ + url: `${DICT_BASE_URL}/page`, + method: "get", + params: queryParams, + }); + } + + /** + * 获取字典表单数据 + * + * @param id 字典ID + * @returns 字典表单数据 + */ + static getFormData(id: number) { + return request >({ + url: `${DICT_BASE_URL}/${id}/form`, + method: "get", + }); + } + + /** + * 新增字典 + * + * @param data 字典表单数据 + */ + static add(data: DictForm) { + return request({ + url: `${DICT_BASE_URL}`, + method: "post", + data: data, + }); + } + + /** + * 修改字典 + * + * @param id 字典ID + * @param data 字典表单数据 + */ + static update(id: number, data: DictForm) { + return request({ + url: `${DICT_BASE_URL}/${id}`, + method: "put", + data: data, + }); + } + + /** + * 删除字典 + * + * @param ids 字典ID,多个以英文逗号(,)分隔 + */ + static deleteByIds(ids: string) { + return request({ + url: `${DICT_BASE_URL}/${ids}`, + method: "delete", + }); + } + + /** + * 获取字典列表 + * + * @returns 字典列表 + */ + static getList() { + return request ({ + url: `${DICT_BASE_URL}/list`, + method: "get", + }); + } + + /** + * 获取字典的数据项 + * + * @param typeCode 字典编码 + * @returns 字典数据项 + */ + static getOptions(code: string) { + return request ({ + url: `${DICT_BASE_URL}/${code}/options`, + method: "get", + }); + } +} + +export default DictAPI; + +/** + * 字典查询参数 + */ +export interface DictPageQuery extends PageQuery { + /** + * 关键字(字典名称/编码) + */ + keywords?: string; +} + +/** + * 字典分页对象 + */ +export interface DictPageVO { + /** + * 字典ID + */ + id: number; + /** + * 字典名称 + */ + name: string; + /** + * 字典编码 + */ + code: string; + /** + * 字典状态(1-启用,0-禁用) + */ + status: number; + /** + * 字典项列表 + */ + dictItems: DictItem[]; +} + +/** + * 字典项 + */ +export interface DictItem { + /** + * 字典项ID + */ + id?: number; + /** + * 字典项名称 + */ + name?: string; + /** + * 字典项值 + */ + value?: string; + /** + * 排序 + */ + sort?: number; + /** + * 状态(1-启用,0-禁用) + */ + status?: number; +} + +// TypeScript 类型声明 + +/** + * 字典 + */ +export interface DictForm { + /** + * 字典ID + */ + id?: number; + /** + * 字典名称 + */ + name?: string; + /** + * 字典编码 + */ + code?: string; + /** + * 字典状态(1-启用,0-禁用) + */ + status?: number; + /** + * 备注 + */ + remark?: string; + /** + * 字典数据项列表 + */ + dictItems?: DictItem[]; +} diff --git a/src/api/file.ts b/src/api/file.ts new file mode 100644 index 0000000..c812520 --- /dev/null +++ b/src/api/file.ts @@ -0,0 +1,74 @@ +import request from "@/utils/request"; + +class FileAPI { + /** + * 文件上传地址 + */ + static uploadUrl = import.meta.env.VITE_APP_BASE_API + "/api/v1/files"; + + /** + * 上传文件 + * + * @param file + */ + static upload(file: File, type: string) { + const formData = new FormData(); + formData.append("file", file); + formData.append("type", type); + return request ({ + url: "/api/v1/files", + method: "post", + timeout: 300000, + data: formData, + headers: { + "Content-Type": "multipart/form-data", + }, + }); + } + + /** + * 删除文件 + * + * @param filePath 文件完整路径 + */ + static deleteByPath(filePath?: string) { + return request({ + url: "/api/v1/files", + method: "delete", + params: { filePath: filePath }, + }); + } + + /** + * 下载文件 + * @param url + * @param fileName + */ + static downloadFile(url: string, fileName?: string) { + return request({ + url: url, + method: "get", + responseType: "blob", + }).then((res) => { + const blob = new Blob([res.data]); + const a = document.createElement("a"); + const url = window.URL.createObjectURL(blob); + a.href = url; + a.download = fileName || "下载文件"; + a.click(); + window.URL.revokeObjectURL(url); + }); + } +} + +export default FileAPI; + +/** + * 文件API类型声明 + */ +export interface FileInfo { + /** 文件名 */ + name: string; + /** 文件路径 */ + url: string; +} diff --git a/src/api/helper.ts b/src/api/helper.ts new file mode 100644 index 0000000..4f74dd5 --- /dev/null +++ b/src/api/helper.ts @@ -0,0 +1,86 @@ +import request from "@/utils/request"; +import { ColoredType } from "@/enums/SoftwareEnum"; + +const HELPER_BASE_URL = "/api/v1/helper"; + +class HelpAPI { + static listQnA(id: number) { + return request ({ + url: `${HELPER_BASE_URL}/listQnA/${id}`, + method: "get", + }); + } + + static getPage(queryParams: QnAPageQuery) { + return request >({ + url: `${HELPER_BASE_URL}/pageQnA`, + method: "get", + params: queryParams, + }); + } + + static setByIds(ids: string, state: number) { + return request({ + url: `${HELPER_BASE_URL}/setQnAByIds/${ids}`, + method: "put", + params: { state: state }, + }); + } + + static saveOrUpdate(data: UpdateQnA) { + return request({ + url: `${HELPER_BASE_URL}/updateQnA`, + method: "put", + data: data, + }); + } +} + +export default HelpAPI; + +export interface QnAPageQuery extends PageQuery { + userId?: number; + state?: number; + typeIds?: string; +} + +/** 问题简要信息 */ +export interface HelpQnA { + /** ID */ + helpId: number; + question: string; + answer: string; +} + +// export interface QnAType { +// color: string; +// value: string; +// label: string; +// } + +/** 问题简要信息 */ +export interface FullQnA { + /** ID */ + helpId?: number; + question?: string; + answer?: string; + helpTypeId?: string; //提问类型 + types?: ColoredType[]; + submitVersinos?: string; //提交问题的软件版本 + userId?: number; //提问用户 + userName?: string; + nickname?: string; + state?: number; //编辑状态 + editTime?: number; //提交时间 + answerTime?: number; //处理时间 +} + +/** 问题简要信息 */ +export interface UpdateQnA { + /** ID */ + helpId?: number; + question?: string; + answer?: string; + helpTypeId?: string; + state?: number; +} diff --git a/src/api/integral.ts b/src/api/integral.ts new file mode 100644 index 0000000..fe5fa9d --- /dev/null +++ b/src/api/integral.ts @@ -0,0 +1,56 @@ +import request from "@/utils/request"; + +const INTEGRAL_BASE_URL = "/api/v1/integral"; + +class IntegralAPI { + static listAdmin(query: IntegralPageQuery) { + return request >({ + url: `${INTEGRAL_BASE_URL}/pageAdmin`, + method: "get", + params: query, + }); + } + + static listUser(query: IntegralPageQuery) { + return request >({ + url: `${INTEGRAL_BASE_URL}/pageUser`, + method: "get", + params: query, + }); + } +} + +export default IntegralAPI; + +export interface IntegralPageAdminVO { + detailsId: number; + userId: number; + userName: string; + nickName?: string; + title: string; + score: number; + balance: number; + //类型规则编号(-1:订制音乐服务;-2:退订音乐服务;-3:音乐服务收入;-4:保存音频;-5:保存midi;-6:积分发放;-7:购买VIP;;-8:提现;-9:推荐音乐;-10:风格收入;-11:购买CPJ;-12:出售CPJ;-13:购买金曲票数;-14:领奖;-15:论坛金钱兑换) + ruleid: number; + ruletype: number; + addtime: number; + comment: string; +} + +export interface IntegralPageUserVO { + detailsId: number; + title: string; + score: number; + balance: number; + ruleid: number; + ruletype: number; + addtime: number; + comment: string; +} + +export interface IntegralPageQuery extends PageQuery { + userId?: number; + ruletype?: number; + /** 添加时间 */ + addtime?: [number, number]; +} diff --git a/src/api/log.ts b/src/api/log.ts new file mode 100644 index 0000000..a8c71e5 --- /dev/null +++ b/src/api/log.ts @@ -0,0 +1,122 @@ +import request from "@/utils/request"; + +const LOG_BASE_URL = "/api/v1/logs"; + +class LogAPI { + /** + * 获取日志分页列表 + * + * @param queryParams 查询参数 + */ + static getPage(queryParams: LogPageQuery) { + return request >({ + url: `${LOG_BASE_URL}/page`, + method: "get", + params: queryParams, + }); + } + + /** + * 获取访问趋势 + * + * @param queryParams + * @returns + */ + static getVisitTrend(queryParams: VisitTrendQuery) { + return request ({ + url: `${LOG_BASE_URL}/visit-trend`, + method: "get", + params: queryParams, + }); + } + + /** + * 获取访问趋势 + * + * @param queryParams + * @returns + */ + static getVisitStats() { + return request ({ + url: `${LOG_BASE_URL}/visit-stats`, + method: "get", + }); + } +} + +export default LogAPI; + +/** + * 日志分页查询对象 + */ +export interface LogPageQuery extends PageQuery { + /** 搜索关键字 */ + keywords?: string; + /** 操作时间 */ + createTime?: [string, string]; +} + +/** + * 系统日志分页VO + */ +export interface LogPageVO { + /** 主键 */ + id: number; + /** 日志模块 */ + module: string; + /** 日志内容 */ + content: string; + /** 请求路径 */ + requestUri: string; + /** 请求方法 */ + method: string; + /** IP 地址 */ + ip: string; + /** 地区 */ + region: string; + /** 浏览器 */ + browser: string; + /** 终端系统 */ + os: string; + /** 执行时间(毫秒) */ + executionTime: number; + /** 操作人 */ + operator: string; +} + +/** 访问趋势视图对象 */ +export interface VisitTrendVO { + /** 日期列表 */ + dates: string[]; + /** 浏览量(PV) */ + pvList: number[]; + /** 访客数(UV) */ + uvList: number[]; + /** IP数 */ + ipList: number[]; +} + +/** 访问趋势查询参数 */ +export interface VisitTrendQuery { + /** 开始日期 */ + startDate: string; + /** 结束日期 */ + endDate: string; +} + +/** 访问统计 */ +export interface VisitStatsVO { + /** 标题 */ + title: string; + /** 类型 */ + type: "pv" | "uv" | "ip"; + + /** 今日访问量 */ + todayCount: number; + /** 总访问量 */ + totalCount: number; + /** 同比增长率(相对于昨天同一时间段的增长率) */ + growthRate: number; + + totalCountOutput: number; +} diff --git a/src/api/menu.ts b/src/api/menu.ts new file mode 100644 index 0000000..b2fb9ba --- /dev/null +++ b/src/api/menu.ts @@ -0,0 +1,209 @@ +import request from "@/utils/request"; +// 菜单基础URL +const MENU_BASE_URL = "/api/v1/menus"; + +class MenuAPI { + /** + * 获取当前用户的路由列表 + * + * 无需传入角色,后端解析token获取角色自行判断是否拥有路由的权限 + * + * @returns 路由列表 + */ + static getRoutes() { + return request ({ + url: `${MENU_BASE_URL}/routes`, + method: "get", + }); + } + + /** + * 获取菜单树形列表 + * + * @param queryParams 查询参数 + * @returns 菜单树形列表 + */ + static getList(queryParams: MenuQuery) { + return request ({ + url: `${MENU_BASE_URL}`, + method: "get", + params: queryParams, + }); + } + + /** + * 获取菜单下拉数据源 + * + * @returns 菜单下拉数据源 + */ + static getOptions(onlyParent?: boolean) { + return request ({ + url: `${MENU_BASE_URL}/options`, + method: "get", + params: { onlyParent: onlyParent }, + }); + } + + /** + * 获取菜单表单数据 + * + * @param id 菜单ID + */ + static getFormData(id: number) { + return request ({ + url: `${MENU_BASE_URL}/${id}/form`, + method: "get", + }); + } + + /** + * 添加菜单 + * + * @param data 菜单表单数据 + * @returns 请求结果 + */ + static add(data: MenuForm) { + return request({ + url: `${MENU_BASE_URL}`, + method: "post", + data: data, + }); + } + + /** + * 修改菜单 + * + * @param id 菜单ID + * @param data 菜单表单数据 + * @returns 请求结果 + */ + static update(id: string, data: MenuForm) { + return request({ + url: `${MENU_BASE_URL}/${id}`, + method: "put", + data: data, + }); + } + + /** + * 删除菜单 + * + * @param id 菜单ID + * @returns 请求结果 + */ + static deleteById(id: number) { + return request({ + url: `${MENU_BASE_URL}/${id}`, + method: "delete", + }); + } +} + +export default MenuAPI; + +import { MenuTypeEnum } from "@/enums/MenuTypeEnum"; + +/** 菜单查询参数 */ +export interface MenuQuery { + /** 搜索关键字 */ + keywords?: string; +} + +/** 菜单视图对象 */ +export interface MenuVO { + /** 子菜单 */ + children?: MenuVO[]; + /** 组件路径 */ + component?: string; + /** ICON */ + icon?: string; + /** 菜单ID */ + id?: number; + /** 菜单名称 */ + name?: string; + /** 父菜单ID */ + parentId?: number; + /** 按钮权限标识 */ + perm?: string; + /** 跳转路径 */ + redirect?: string; + /** 路由名称 */ + routeName?: string; + /** 路由相对路径 */ + routePath?: string; + /** 菜单排序(数字越小排名越靠前) */ + sort?: number; + /** 菜单 */ + type?: MenuTypeEnum; + /** 菜单是否可见(1:显示;0:隐藏) */ + visible?: number; +} + +/** 菜单表单对象 */ +export interface MenuForm { + /** 菜单ID */ + id?: string; + /** 父菜单ID */ + parentId?: number; + /** 菜单名称 */ + name?: string; + /** 菜单是否可见(1-是 0-否) */ + visible: number; + /** ICON */ + icon?: string; + /** 排序 */ + sort?: number; + /** 路由名称 */ + routeName?: string; + /** 路由路径 */ + routePath?: string; + /** 组件路径 */ + component?: string; + /** 跳转路由路径 */ + redirect?: string; + /** 菜单 */ + type?: MenuTypeEnum; + /** 权限标识 */ + perm?: string; + /** 【菜单】是否开启页面缓存 */ + keepAlive?: number; + /** 【目录】只有一个子路由是否始终显示 */ + alwaysShow?: number; + /** 参数 */ + params?: KeyValue[]; +} + +interface KeyValue { + key: string; + value: string; +} + +/** RouteVO,路由对象 */ +export interface RouteVO { + /** 子路由列表 */ + children: RouteVO[]; + /** 组件路径 */ + component?: string; + /** 路由属性 */ + meta?: Meta; + /** 路由名称 */ + name?: string; + /** 路由路径 */ + path?: string; + /** 跳转链接 */ + redirect?: string; +} + +/** Meta,路由属性 */ +export interface Meta { + /** 【目录】只有一个子路由是否始终显示 */ + alwaysShow?: boolean; + /** 是否隐藏(true-是 false-否) */ + hidden?: boolean; + /** ICON */ + icon?: string; + /** 【菜单】是否开启页面缓存 */ + keepAlive?: boolean; + /** 路由title */ + title?: string; +} diff --git a/src/api/message.ts b/src/api/message.ts new file mode 100644 index 0000000..6b30962 --- /dev/null +++ b/src/api/message.ts @@ -0,0 +1,57 @@ +import request from "@/utils/request"; + +const MESSAGE_BASE_URL = "/api/v1/message"; + +class MessageAPI { + static getPage(queryParams: MessagePageQuery) { + return request >({ + url: `${MESSAGE_BASE_URL}/page`, + method: "get", + params: queryParams, + }); + } + static getLatest(userId: number) { + return request ({ + url: `${MESSAGE_BASE_URL}/${userId}/latest`, + method: "get", + }); + } + static setByIds(ids: string, state: number) { + return request({ + url: `${MESSAGE_BASE_URL}/${ids}`, + method: "put", + params: { state: state }, + }); + } + + static save(data: WebMessage) { + return request({ + url: `${MESSAGE_BASE_URL}/save`, + method: "put", + data: data, + }); + } +} + +export default MessageAPI; + +export interface MessagePageQuery extends PageQuery { + userId?: number; + type: number; +} + +export interface WebMessage { + msgId?: number; + + userId?: number; + + title?: string; + content?: string; + + state?: number; + type?: number; + + sendTime?: number; + readTime?: number; + deleteTime?: number; +} diff --git a/src/api/notice.ts b/src/api/notice.ts new file mode 100644 index 0000000..8ad9be6 --- /dev/null +++ b/src/api/notice.ts @@ -0,0 +1,48 @@ +import request from "@/utils/request"; + +const NOTICE_BASE_URL = "/api/v1/notice"; + +class NoticeAPI { + static getPage(queryParams: NoticePageQuery) { + return request >({ + url: `${NOTICE_BASE_URL}/page`, + method: "get", + params: queryParams, + }); + } + + static save(data: WebNotice) { + return request({ + url: `${NOTICE_BASE_URL}/save`, + method: "put", + data: data, + }); + } + + static setByIds(ids: string, state: number) { + return request({ + url: `${NOTICE_BASE_URL}/${ids}`, + method: "put", + params: { state: state }, + }); + } +} + +export default NoticeAPI; + +export interface NoticePageQuery extends PageQuery { + state?: number; +} + +export interface WebNotice { + noticeId?: number; + + title?: string; + content?: string; + + state?: number; + noticeType?: number; + + releaseTime?: number; + shieldTime?: number; +} diff --git a/src/api/order.ts b/src/api/order.ts new file mode 100644 index 0000000..65482e4 --- /dev/null +++ b/src/api/order.ts @@ -0,0 +1,37 @@ +import request from "@/utils/request"; + +const ORDER_BASE_URL = "/api/v1/order"; + +class OrderAPI { + static listPage(query: OrderPageQuery) { + return request >({ + url: `${ORDER_BASE_URL}/page`, + method: "get", + params: query, + }); + } +} + +export default OrderAPI; + +export interface OrderPageVO { + orderId: number; + userId: number; + userName: string; + nickName?: string; + money: number; + orderNumber: string; + payway: string; + state: number; + paytime: number; + endtime?: number; + remark?: string; +} + +export interface OrderPageQuery extends PageQuery { + userId?: number; + state?: number; + payway?: string; + /** 添加时间 */ + paytime?: [number, number]; +} diff --git a/src/api/role.ts b/src/api/role.ts new file mode 100644 index 0000000..e33a502 --- /dev/null +++ b/src/api/role.ts @@ -0,0 +1,139 @@ +import request from "@/utils/request"; + +const ROLE_BASE_URL = "/api/v1/roles"; + +class RoleAPI { + /** 获取角色分页数据 */ + static getPage(queryParams?: RolePageQuery) { + return request >({ + url: `${ROLE_BASE_URL}/page`, + method: "get", + params: queryParams, + }); + } + + /** 获取角色下拉数据源 */ + static getOptions() { + return request ({ + url: `${ROLE_BASE_URL}/options`, + method: "get", + }); + } + + /** + * 获取角色的菜单ID集合 + * + * @param roleId 角色ID + * @returns 角色的菜单ID集合 + */ + static getRoleMenuIds(roleId: number) { + return request ({ + url: `${ROLE_BASE_URL}/${roleId}/menuIds`, + method: "get", + }); + } + + /** + * 分配菜单权限 + * + * @param roleId 角色ID + * @param data 菜单ID集合 + */ + static updateRoleMenus(roleId: number, data: number[]) { + return request({ + url: `${ROLE_BASE_URL}/${roleId}/menus`, + method: "put", + data: data, + }); + } + + /** + * 获取角色表单数据 + * + * @param id 角色ID + * @returns 角色表单数据 + */ + static getFormData(id: number) { + return request ({ + url: `${ROLE_BASE_URL}/${id}/form`, + method: "get", + }); + } + + /** 添加角色 */ + static add(data: RoleForm) { + return request({ + url: `${ROLE_BASE_URL}`, + method: "post", + data: data, + }); + } + + /** + * 更新角色 + * + * @param id 角色ID + * @param data 角色表单数据 + */ + static update(id: number, data: RoleForm) { + return request({ + url: `${ROLE_BASE_URL}/${id}`, + method: "put", + data: data, + }); + } + + /** + * 批量删除角色,多个以英文逗号(,)分割 + * + * @param ids 角色ID字符串,多个以英文逗号(,)分割 + */ + static deleteByIds(ids: string) { + return request({ + url: `${ROLE_BASE_URL}/${ids}`, + method: "delete", + }); + } +} + +export default RoleAPI; + +/** 角色分页查询参数 */ +export interface RolePageQuery extends PageQuery { + /** 搜索关键字 */ + keywords?: string; +} + +/** 角色分页对象 */ +export interface RolePageVO { + /** 角色编码 */ + code?: string; + /** 角色ID */ + id?: number; + /** 角色名称 */ + name?: string; + /** 排序 */ + sort?: number; + /** 角色状态 */ + status?: number; + /** 创建时间 */ + createTime?: Date; + /** 修改时间 */ + updateTime?: Date; +} + +/** 角色表单对象 */ +export interface RoleForm { + /** 角色ID */ + id?: number; + /** 角色编码 */ + code: string; + /** 数据权限 */ + dataScope?: number; + /** 角色名称 */ + name: string; + /** 排序 */ + sort?: number; + /** 角色状态(1-正常;0-停用) */ + status?: number; +} diff --git a/src/api/software.ts b/src/api/software.ts new file mode 100644 index 0000000..688cc03 --- /dev/null +++ b/src/api/software.ts @@ -0,0 +1,130 @@ +import request from "@/utils/request"; + +const SOFTWARE_BASE_URL = "/api/v1/software"; + +class SoftwareAPI { + static listSoftware() { + return request ({ + url: `${SOFTWARE_BASE_URL}/list`, + method: "get", + }); + } + + static listFont() { + return request ({ + url: `${SOFTWARE_BASE_URL}/listFont`, + method: "get", + }); + } + + static getVersion(id: number, os: number) { + return request ({ + url: `${SOFTWARE_BASE_URL}/lastVersion/${id}/${os}`, + method: "get", + }); + } + + static page(query: VersionPageQuery) { + return request >({ + url: `${SOFTWARE_BASE_URL}/page`, + method: "get", + params: query, + }); + } + + static update(data: FullVersion) { + return request({ + url: `${SOFTWARE_BASE_URL}/update`, + method: "put", + data: data, + }); + } + + static maxVersion(swId: number, innerId: number) { + return request ({ + url: `${SOFTWARE_BASE_URL}/maxVersion`, + method: "get", + params: { softwareId: swId, innerId: innerId }, + }); + } + + static swDownload(swId: number, os: number) { + return request({ + url: `${SOFTWARE_BASE_URL}/swDownload`, + method: "put", + params: { softwareId: swId, os: os }, + }); + } + + static setByIds(ids: string, state: number) { + return request({ + url: `${SOFTWARE_BASE_URL}/${ids}`, + method: "put", + params: { state: state }, + }); + } +} + +export default SoftwareAPI; + +/** 软件信息 */ +export interface SoftwareInfo { + /** 软件ID */ + softwareId: number; + /** 软件名称 */ + name: string; + /** 适用系统 */ + os: number; +} + +/** 版本信息 */ +export interface VersionInfo { + softwareId: number; + os: number; + version: string; + installPath: string; + releaseDate: number; + packageSize: number; + describe?: string; + pictures?: string[]; +} + +/** 音色库信息 */ +export interface FontInfo { + fontsId: number; + name: string; + path: string; + size: number; + describe?: string; +} + +export interface VersionPageQuery extends PageQuery { + softwareId?: number; + innerId?: number; + incompatible?: number; +} + +export interface FullVersion { + versionId?: number; + softwareId?: number; + innerId?: number; + versionMajor?: number; + versionMinor?: number; + versionModify?: number; + versionBuild?: number; + incompatible?: number; + installSize?: number; + installPath?: string; + releaseTime?: number; + describeText?: string; + accessNum?: number; + downloadNum?: number; + isDeleted?: number; +} + +export interface VersionNum { + major: number; + minor: number; + modify: number; + build: number; +} diff --git a/src/api/statistics.ts b/src/api/statistics.ts new file mode 100644 index 0000000..a428d83 --- /dev/null +++ b/src/api/statistics.ts @@ -0,0 +1,48 @@ +import request from "@/utils/request"; + +const STATISTICS_BASE_URL = "/api/v1/statistics"; + +class StatisticsAPI { + static page(query: StatisticsPageQuery) { + return request >({ + url: `${STATISTICS_BASE_URL}/page`, + method: "get", + params: query, + }); + } +} + +export default StatisticsAPI; + +export interface StatisticsBO { + statisticsId?: number; + statisticsDate?: number; //统计日期 + login?: string; //登录次数 + loginUsersum?: string; //登录人数 + register?: string; //注册人数 + mofangAccess?: string; //软件使用次数 + downloadNum?: string; //软件下载次数 + accompanyUse?: string; //风格使用次数 + accompanyConsume?: string; //风格消费额 + recharge?: string; //音符充值 + consume?: string; //音符消费 +} + +export interface StatisticsVO { + statisticsId?: number; + statisticsDate?: number; //统计日期 + login?: number[]; //登录次数 + loginUsersum?: number[]; //登录人数 + register?: number[]; //注册人数 + mofangAccess?: number[]; //软件使用次数 + downloadNum?: number[]; //软件下载次数 + accompanyUse?: number[]; //风格使用次数 + accompanyConsume?: number[]; //风格消费总额 + recharge?: number[]; //音符充值 + consume?: number[]; //音符消费 +} + +export interface StatisticsPageQuery extends PageQuery { + /** 时间范围 */ + range?: [number, number]; +} diff --git a/src/api/style.ts b/src/api/style.ts new file mode 100644 index 0000000..5285514 --- /dev/null +++ b/src/api/style.ts @@ -0,0 +1,68 @@ +import request from "@/utils/request"; + +const STYLE_BASE_URL = "/api/v1/style"; + +class StyleAPI { + static statistic() { + return request ({ + url: `${STYLE_BASE_URL}/statistic`, + method: "get", + }); + } + + static page(query: StylePageQuery) { + return request >({ + url: `${STYLE_BASE_URL}/page`, + method: "get", + params: query, + }); + } + + static update(data: StyleUpdate) { + return request({ + url: `${STYLE_BASE_URL}/update`, + method: "put", + data: data, + }); + } +} + +export default StyleAPI; + +export interface StyleStatistic { + ts0: number; + ts1: number; + ts2: number; + ts3: number; + temp: number; +} + +export interface StyleVO { + accompanyId: number; + + cost: number; //使用价格 + score: number; //评分 + state: number; //状态 + name: string; //风格名称 + description?: string; //风格描述 + author: number; //作者ID + authorName?: string; //作者昵称 + timesignature: number; //节拍(0:4/4;1:3/4;2:2/4;3:6/8) + tempo: number; //速度 + changeTime: number; //编辑时间 + scoreTime: number; //评分时间 + useCount: number; //使用次数 + sellCount: number; //购买次数 +} + +export interface StylePageQuery extends PageQuery { + author?: number; + ts?: number; + state?: number; +} + +export interface StyleUpdate { + accompanyId?: number; + cost?: number; //使用价格 + state?: number; //状态 +} diff --git a/src/api/user.ts b/src/api/user.ts new file mode 100644 index 0000000..93af898 --- /dev/null +++ b/src/api/user.ts @@ -0,0 +1,612 @@ +import request from "@/utils/request"; +import { SendCodeData } from "./auth"; + +const USER_BASE_URL = "/api/v1/users"; + +class UserAPI { + /** + * 获取当前登录用户信息 + * + * @returns 登录用户昵称、头像信息,包括角色和权限 + */ + static getInfo() { + return request ({ + url: `${USER_BASE_URL}/me`, + method: "get", + }); + } + + /** + * 获取用户分页列表 + * + * @param queryParams 查询参数 + */ + static getPage(queryParams: UserPageQuery) { + return request >({ + url: `${USER_BASE_URL}/page`, + method: "get", + params: queryParams, + }); + } + + /** + * 获取用户表单详情 + * + * @param userId 用户ID + * @returns 用户表单详情 + */ + static getFormData(userId: number) { + return request ({ + url: `${USER_BASE_URL}/${userId}/form`, + method: "get", + }); + } + + /** + * 添加用户 + * + * @param data 用户表单数据 + */ + static add(data: UserForm) { + return request({ + url: `${USER_BASE_URL}`, + method: "post", + data: data, + }); + } + + /** + * 修改用户 + * + * @param id 用户ID + * @param data 用户表单数据 + */ + static update(id: number, data: UserForm) { + return request({ + url: `${USER_BASE_URL}/${id}`, + method: "put", + data: data, + }); + } + + // /** + // * 修改用户密码 + // * + // * @param id 用户ID + // * @param password 新密码 + // */ + // static resetPassword(id: number, password: string) { + // return request({ + // url: `${USER_BASE_URL}/${id}/password/reset`, + // method: "put", + // params: { password: password }, + // }); + // } + + /** + * 批量删除用户,多个以英文逗号(,)分割 + * + * @param ids 用户ID字符串,多个以英文逗号(,)分割 + */ + static deleteByIds(ids: string) { + return request({ + url: `${USER_BASE_URL}/${ids}`, + method: "delete", + }); + } + + /** + * 批量修改用户状态,多个以英文逗号(,)分割 + * + * @param ids 用户ID字符串,多个以英文逗号(,)分割 + */ + static setStateByIds(ids: string, state: number) { + return request({ + url: `${USER_BASE_URL}/${ids}/${state}`, + method: "patch", + }); + } + + /** 下载用户导入模板 */ + static downloadTemplate() { + return request({ + url: `${USER_BASE_URL}/template`, + method: "get", + responseType: "arraybuffer", + }); + } + + /** + * 导出用户 + * + * @param queryParams 查询参数 + */ + static export(queryParams: UserPageQuery) { + return request({ + url: `${USER_BASE_URL}/export`, + method: "get", + params: queryParams, + responseType: "arraybuffer", + }); + } + + /** + * 导入用户 + * + * @param deptId 部门ID + * @param file 导入文件 + */ + static import(deptId: number, file: File) { + const formData = new FormData(); + formData.append("file", file); + return request({ + url: `${USER_BASE_URL}/import`, + method: "post", + params: { deptId: deptId }, + data: formData, + headers: { + "Content-Type": "multipart/form-data", + }, + }); + } + + /** 获取个人中心用户信息 */ + static getProfile() { + return request ({ + url: `${USER_BASE_URL}/profile`, + method: "get", + }); + } + + /** 修改个人中心用户信息 */ + static updateProfile(data: UserProfileForm) { + return request({ + url: `${USER_BASE_URL}/profile`, + method: "put", + data: data, + }); + } + + /** 修改个人中心用户密码 */ + static changePassword(data: PasswordChangeForm) { + return request({ + url: `${USER_BASE_URL}/password`, + method: "put", + data: data, + }); + } + + /** + * 发送手机/邮箱验证码 + * + * @param contact 联系方式 手机号/邮箱 + */ + static sendBindCode(data: SendCodeData) { + const formData = new FormData(); + formData.append("contact", data.contact); + formData.append("captchaKey", data.captchaKey); + formData.append("captchaCode", data.captchaCode); + + return request({ + url: `${USER_BASE_URL}/sendBindCode`, + method: "post", + data: formData, + headers: { + "Content-Type": "multipart/form-data", + }, + }); + } + + /** 绑定个人中心用户手机 */ + static bindMobile(data: MobileBindingForm) { + return request({ + url: `${USER_BASE_URL}/mobile`, + method: "put", + data: data, + }); + } + + /** 绑定个人中心用户邮箱 */ + static bindEmail(data: EmailBindingForm) { + return request({ + url: `${USER_BASE_URL}/email`, + method: "put", + data: data, + }); + } + + /** 获取账户信息 */ + static getAccountInfo() { + return request ({ + url: `${USER_BASE_URL}/account`, + method: "get", + }); + } + + /** + * 修改用户昵称 + * + * @param id 用户ID + * @param nickname 用户昵称 + */ + static updateNickname(id: number, nickname: string) { + return request({ + url: `${USER_BASE_URL}/${id}/nickname`, + method: "patch", + params: { nickname: nickname }, + }); + } + + /** + * 修改用户手机 + * + * @param id 用户ID + * @param phone 用户手机号 + */ + static updatePhone(id: number, phone: string) { + return request({ + url: `${USER_BASE_URL}/${id}/phone`, + method: "patch", + params: { phone: phone }, + }); + } + + /** 修改个人中心用户密码 */ + static resetPassword(data: ResetPasswordForm) { + return request({ + url: `${USER_BASE_URL}/resetPassword`, + method: "post", + data: data, + }); + } + + /** 获取用户实名认证信息 */ + static getRealNameInfo() { + return request ({ + url: `${USER_BASE_URL}/realname`, + method: "get", + }); + } + + /** 更新用户实名认证信息 */ + static updateRealNameInfo(data: RealNameInfo) { + return request({ + url: `${USER_BASE_URL}/realname`, + method: "put", + data: data, + }); + } + + static getRealNamePage(queryParams: PageQuery) { + return request >({ + url: `${USER_BASE_URL}/realname/page`, + method: "get", + params: queryParams, + }); + } + + static verifyRealName(userId: number, reason: string) { + return request({ + url: `${USER_BASE_URL}/${userId}/realname`, + method: "post", + params: { reason: reason }, + }); + } + + static beingVIP(vipType: number) { + return request ({ + url: `${USER_BASE_URL}/vip`, + method: "post", + params: { vipType: vipType }, + }); + } + + static buyNotes(payType: string, amount: string) { + return request ({ + url: `${USER_BASE_URL}/buyNotes`, + method: "post", + params: { payType: payType, amount: amount }, + }); + } + + static checkOrder(order: string) { + return request ({ + url: `${USER_BASE_URL}/checkOrder`, + method: "get", + params: { order: order }, + }); + } + + static draw(data: DrawForm) { + return request ({ + url: `${USER_BASE_URL}/draw`, + method: "post", + data: data, + }); + } + + static drawPage(queryParams: PageQuery) { + return request >({ + url: `${USER_BASE_URL}/draw/page`, + method: "get", + params: queryParams, + }); + } + + static verifyDraw(orderId: number, reason: string) { + return request ({ + url: `${USER_BASE_URL}/draw`, + method: "put", + params: { orderId: orderId, reason: reason }, + }); + } +} + +export default UserAPI; + +/** 登录用户信息 */ +export interface UserInfo { + /** 用户ID */ + userId?: number; + + /** 用户名 */ + username?: string; + + /** 昵称 */ + nickname?: string; + + /** 头像URL */ + avatar?: string; + + /** 角色 */ + roles: string[]; + + /** 权限 */ + perms: string[]; +} + +/** + * 用户分页查询对象 + */ +export interface UserPageQuery extends PageQuery { + /** 搜索关键字 */ + keywords?: string; + + /** 用户状态 */ + status?: number; + + /** 部门ID */ + // deptId?: number; + + /** 注册时间 */ + regTime?: [number, number]; +} + +/** 用户分页对象 */ +export interface UserPageVO { + /** 用户头像URL */ + avatar?: string; + /** 创建时间 */ + regTime?: number; + /** 部门名称 */ + // deptName?: string; + /** 用户邮箱 */ + email?: string; + /** 性别 */ + genderLabel?: string; + /** 用户ID */ + id?: number; + /** 手机号 */ + mobile?: string; + /** 用户昵称 */ + nickname?: string; + /** 角色名称,多个使用英文逗号(,)分割 */ + // roleNames?: string; + /** 用户状态(1:启用;0:禁用) */ + status?: number; + /** 用户名 */ + username?: string; + + name?: string; + isName?: number; + isPhone?: number; + loginTime?: number; + loginNum?: number; + deleteTime?: number; + vipTime?: number; + integral?: number; + authority?: number; +} + +/** 用户表单类型 */ +export interface UserForm { + /** 用户头像 */ + avatar?: string; + /** 部门ID */ + // deptId?: number; + /** 邮箱 */ + email?: string; + /** 性别 */ + gender?: number; + /** 用户ID */ + id?: number; + /** 手机号 */ + mobile?: string; + /** 昵称 */ + nickname?: string; + /** 角色ID集合 */ + roleIds?: number[]; + /** 用户状态(1:正常;0:禁用) */ + status?: number; + /** 用户名 */ + username?: string; +} + +/** 个人中心用户信息 */ +export interface UserProfileVO { + /** 用户ID */ + id?: number; + + /** 用户名 */ + username?: string; + + /** 昵称 */ + nickname?: string; + + /** 头像URL */ + avatar?: string; + + /** 性别 */ + gender?: number; + + /** 手机号 */ + mobile?: string; + + /** 邮箱 */ + email?: string; + + // /** 部门名称 */ + // deptName?: string; + + /** 角色名称,多个使用英文逗号(,)分割 */ + roleNames?: string; + + /** 创建时间 */ + createTime?: Date; +} + +/** 个人中心用户信息表单 */ +export interface UserProfileForm { + /** 用户ID */ + id?: number; + + /** 用户名 */ + username?: string; + + /** 昵称 */ + nickname?: string; + + /** 头像URL */ + avatar?: string; + + /** 性别 */ + gender?: number; + + /** 手机号 */ + mobile?: string; + + /** 邮箱 */ + email?: string; +} + +/** 修改密码表单 */ +export interface PasswordChangeForm { + /** 原密码 */ + oldPassword?: string; + /** 新密码 */ + newPassword?: string; + /** 确认新密码 */ + confirmPassword?: string; +} + +/** 重置密码表单 */ +export interface ResetPasswordForm { + /** 用户ID */ + userId?: number; + /** 用户名 */ + username?: string; + /** 手机或邮箱 */ + contact?: string; + /** 验证码 */ + verifyCode?: string; + /** 密码 */ + password?: string; +} + +/** 修改手机表单 */ +export interface MobileBindingForm { + /** 手机号 */ + mobile?: string; + /** 验证码 */ + code?: string; +} + +/** 修改邮箱表单 */ +export interface EmailBindingForm { + /** 邮箱 */ + email?: string; + /** 验证码 */ + code?: string; +} + +/** 账户信息 */ +export interface AccountInfo { + /** 用户ID */ + userId?: number; + /** 账户状态(0:注销;1:锁定;2:已激活;3:未激活;4:在线;5:旧版用户) */ + state?: number; + + /** 真实名称 */ + name?: string; + /** 是否实名认证(1:是;2:不是;3:正在认证) */ + isName?: number; + + /** 手机号 */ + phone?: string; + /** 是否手机认证(1:是;2:不是) */ + isPhone?: number; + + /** 邮箱 */ + email?: string; + /** 邮箱激活时间 */ + // activateTime?: number; + + /** 唱作音符数 */ + integral?: number; + + /** VIP过期时间(-1:终身, -2: 已过期, 0: 非会员) */ + vipTime?: number; + /** VIP状态 */ + // vipState?: number; + + /** 注册时间 */ + regTime?: number; +} + +export interface RealNameInfo { + /** 用户ID */ + userId?: number; + + /** 真实名称 */ + name?: string; + isName?: number; + + identityType?: number; //证件类型 + identityCard?: string; //证件号 + identityPic?: string; //证件照片 + address?: string; //联系地址 +} + +export interface RealNameInfoPageQuery extends PageQuery { + isName?: number; +} + +export interface DrawForm { + amount: number; + cardNum: string; + bankName: string; + cardName?: string; +} + +export interface DrawPageVO { + orderId: number; + userId: number; + userName: string; + money: string; + bankName: string; + cardNum: string; + cardName?: string; + takeTime: number; + makeTime?: number; + state: number; +} diff --git a/src/assets/icons/alipay-l.svg b/src/assets/icons/alipay-l.svg new file mode 100644 index 0000000..fa2515a --- /dev/null +++ b/src/assets/icons/alipay-l.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/alipay-s.svg b/src/assets/icons/alipay-s.svg new file mode 100644 index 0000000..433f98d --- /dev/null +++ b/src/assets/icons/alipay-s.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/api.svg b/src/assets/icons/api.svg new file mode 100644 index 0000000..0181bdd --- /dev/null +++ b/src/assets/icons/api.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/backtop.svg b/src/assets/icons/backtop.svg new file mode 100644 index 0000000..f8e6aa0 --- /dev/null +++ b/src/assets/icons/backtop.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/captcha.svg b/src/assets/icons/captcha.svg new file mode 100644 index 0000000..8b1da30 --- /dev/null +++ b/src/assets/icons/captcha.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/cascader.svg b/src/assets/icons/cascader.svg new file mode 100644 index 0000000..57209bf --- /dev/null +++ b/src/assets/icons/cascader.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/client.svg b/src/assets/icons/client.svg new file mode 100644 index 0000000..7373b3d --- /dev/null +++ b/src/assets/icons/client.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/close.svg b/src/assets/icons/close.svg new file mode 100644 index 0000000..e99c978 --- /dev/null +++ b/src/assets/icons/close.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/close_all.svg b/src/assets/icons/close_all.svg new file mode 100644 index 0000000..2005198 --- /dev/null +++ b/src/assets/icons/close_all.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/close_left.svg b/src/assets/icons/close_left.svg new file mode 100644 index 0000000..fc5cf71 --- /dev/null +++ b/src/assets/icons/close_left.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/close_other.svg b/src/assets/icons/close_other.svg new file mode 100644 index 0000000..27ffc32 --- /dev/null +++ b/src/assets/icons/close_other.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/close_right.svg b/src/assets/icons/close_right.svg new file mode 100644 index 0000000..b96dc1c --- /dev/null +++ b/src/assets/icons/close_right.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/code.svg b/src/assets/icons/code.svg new file mode 100644 index 0000000..d8b546c --- /dev/null +++ b/src/assets/icons/code.svg @@ -0,0 +1 @@ + diff --git a/src/assets/icons/collapse.svg b/src/assets/icons/collapse.svg new file mode 100644 index 0000000..1507568 --- /dev/null +++ b/src/assets/icons/collapse.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/dict.svg b/src/assets/icons/dict.svg new file mode 100644 index 0000000..db60220 --- /dev/null +++ b/src/assets/icons/dict.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/document.svg b/src/assets/icons/document.svg new file mode 100644 index 0000000..aaa0574 --- /dev/null +++ b/src/assets/icons/document.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/download.svg b/src/assets/icons/download.svg new file mode 100644 index 0000000..a8077dc --- /dev/null +++ b/src/assets/icons/download.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/file.svg b/src/assets/icons/file.svg new file mode 100644 index 0000000..fac9bf0 --- /dev/null +++ b/src/assets/icons/file.svg @@ -0,0 +1 @@ + diff --git a/src/assets/icons/finish-black.svg b/src/assets/icons/finish-black.svg new file mode 100644 index 0000000..53e6fe4 --- /dev/null +++ b/src/assets/icons/finish-black.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/finish-white.svg b/src/assets/icons/finish-white.svg new file mode 100644 index 0000000..f9f87f0 --- /dev/null +++ b/src/assets/icons/finish-white.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/fullscreen-exit.svg b/src/assets/icons/fullscreen-exit.svg new file mode 100644 index 0000000..2452f2b --- /dev/null +++ b/src/assets/icons/fullscreen-exit.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/fullscreen.svg b/src/assets/icons/fullscreen.svg new file mode 100644 index 0000000..4b6ee11 --- /dev/null +++ b/src/assets/icons/fullscreen.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/github.svg b/src/assets/icons/github.svg new file mode 100644 index 0000000..1adfa4e --- /dev/null +++ b/src/assets/icons/github.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/homepage.svg b/src/assets/icons/homepage.svg new file mode 100644 index 0000000..1e1feab --- /dev/null +++ b/src/assets/icons/homepage.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/ip.svg b/src/assets/icons/ip.svg new file mode 100644 index 0000000..087f3bb --- /dev/null +++ b/src/assets/icons/ip.svg @@ -0,0 +1 @@ + diff --git a/src/assets/icons/java.svg b/src/assets/icons/java.svg new file mode 100644 index 0000000..eaa93db --- /dev/null +++ b/src/assets/icons/java.svg @@ -0,0 +1 @@ + diff --git a/src/assets/icons/language.svg b/src/assets/icons/language.svg new file mode 100644 index 0000000..e754062 --- /dev/null +++ b/src/assets/icons/language.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/menu.svg b/src/assets/icons/menu.svg new file mode 100644 index 0000000..f5875d3 --- /dev/null +++ b/src/assets/icons/menu.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/message.svg b/src/assets/icons/message.svg new file mode 100644 index 0000000..deacdc3 --- /dev/null +++ b/src/assets/icons/message.svg @@ -0,0 +1 @@ + diff --git a/src/assets/icons/monitor.svg b/src/assets/icons/monitor.svg new file mode 100644 index 0000000..f153b9c --- /dev/null +++ b/src/assets/icons/monitor.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/project.svg b/src/assets/icons/project.svg new file mode 100644 index 0000000..eaf6a12 --- /dev/null +++ b/src/assets/icons/project.svg @@ -0,0 +1 @@ + diff --git a/src/assets/icons/pv.svg b/src/assets/icons/pv.svg new file mode 100644 index 0000000..cd7da06 --- /dev/null +++ b/src/assets/icons/pv.svg @@ -0,0 +1 @@ + diff --git a/src/assets/icons/qrcode-black.svg b/src/assets/icons/qrcode-black.svg new file mode 100644 index 0000000..0bcd90e --- /dev/null +++ b/src/assets/icons/qrcode-black.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/qrcode-white.svg b/src/assets/icons/qrcode-white.svg new file mode 100644 index 0000000..d73dcb0 --- /dev/null +++ b/src/assets/icons/qrcode-white.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/refresh.svg b/src/assets/icons/refresh.svg new file mode 100644 index 0000000..e598ed1 --- /dev/null +++ b/src/assets/icons/refresh.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/role.svg b/src/assets/icons/role.svg new file mode 100644 index 0000000..5d25278 --- /dev/null +++ b/src/assets/icons/role.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/scan-black.svg b/src/assets/icons/scan-black.svg new file mode 100644 index 0000000..339a285 --- /dev/null +++ b/src/assets/icons/scan-black.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/scan-white.svg b/src/assets/icons/scan-white.svg new file mode 100644 index 0000000..6fb00c0 --- /dev/null +++ b/src/assets/icons/scan-white.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/setting.svg b/src/assets/icons/setting.svg new file mode 100644 index 0000000..fbc4945 --- /dev/null +++ b/src/assets/icons/setting.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/size.svg b/src/assets/icons/size.svg new file mode 100644 index 0000000..f92f852 --- /dev/null +++ b/src/assets/icons/size.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/system.svg b/src/assets/icons/system.svg new file mode 100644 index 0000000..2e6045b --- /dev/null +++ b/src/assets/icons/system.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/table.svg b/src/assets/icons/table.svg new file mode 100644 index 0000000..1a16abb --- /dev/null +++ b/src/assets/icons/table.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/todo.svg b/src/assets/icons/todo.svg new file mode 100644 index 0000000..f48e667 --- /dev/null +++ b/src/assets/icons/todo.svg @@ -0,0 +1 @@ + diff --git a/src/assets/icons/tree.svg b/src/assets/icons/tree.svg new file mode 100644 index 0000000..51aea8f --- /dev/null +++ b/src/assets/icons/tree.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/typescript.svg b/src/assets/icons/typescript.svg new file mode 100644 index 0000000..781d6f8 --- /dev/null +++ b/src/assets/icons/typescript.svg @@ -0,0 +1 @@ + diff --git a/src/assets/icons/unipay.svg b/src/assets/icons/unipay.svg new file mode 100644 index 0000000..431a227 --- /dev/null +++ b/src/assets/icons/unipay.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/user.svg b/src/assets/icons/user.svg new file mode 100644 index 0000000..8e693ec --- /dev/null +++ b/src/assets/icons/user.svg @@ -0,0 +1 @@ + diff --git a/src/assets/icons/uv.svg b/src/assets/icons/uv.svg new file mode 100644 index 0000000..c5be7eb --- /dev/null +++ b/src/assets/icons/uv.svg @@ -0,0 +1 @@ + diff --git a/src/assets/icons/vue.svg b/src/assets/icons/vue.svg new file mode 100644 index 0000000..456f876 --- /dev/null +++ b/src/assets/icons/vue.svg @@ -0,0 +1 @@ + diff --git a/src/assets/icons/wxpay-l.svg b/src/assets/icons/wxpay-l.svg new file mode 100644 index 0000000..be425bd --- /dev/null +++ b/src/assets/icons/wxpay-l.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/wxpay-s.svg b/src/assets/icons/wxpay-s.svg new file mode 100644 index 0000000..c54b63d --- /dev/null +++ b/src/assets/icons/wxpay-s.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/xml.svg b/src/assets/icons/xml.svg new file mode 100644 index 0000000..f041213 --- /dev/null +++ b/src/assets/icons/xml.svg @@ -0,0 +1 @@ + diff --git a/src/assets/images/401.gif b/src/assets/images/401.gif new file mode 100644 index 0000000000000000000000000000000000000000..4c930e72a698889a0f5666d8599652c5808cfc70 GIT binary patch literal 162867 zcmcG!S5%Yz8pZi0gb+x85RoPzozQzPh9c5MR0LF-h*YIX6D9Nx0i^d{rS}?o?}~s* z@4ZR0Fns5HXV#iEGj}t&dhc?x*WUa2?f*SB6-g;mDNqUM S5HlZk~0raPKJhtI#*WRs;U?E_M^T|QM?NPJOT$wa{g9> z10!8E%w1MjR;OoXRyx1D10FOPdjsR`wnDD~0ARj=5Z(c91H9MYz(4;95ME_4N0?is zSr(PrZnxU=jyl`TyOr*H?qA_E>{WTEV8}q$jz@~Ho&sm}PliwW`d+l}dQeC99jo&v zk8a#(uZXRmKaiB@Q2n-l{@bo4=-1U7IE9Xfe?XwCCpHudCwm(d6&<4hL6C aFD -Nvj o^tz<5?|yzf;nzP7p+HiDbTWeKyxgO=Tn@^Kdz# zqxdY%s^u3kszX`g_T-7r+4=Fdv9X)zpM>&V&IRm6_t#l3N^g~gD<4E7C%q3D*YtuP zr8b_{4^Y!z3?Mc1WtNV&M=$vu#-3#gZHEP=L%3UAM}kM)KC^r{8{WtW7OaeBc_;4i zN+ELZdBO`mh-|qLA@3}@JrZ-YK7}g^TQ(w8ovjB5wOaG3KYr|!WRF!VvINB$%=P7R zk}Te1PvA3T!X)x9xveo+6*XAIvg$Hn66^!&uqjSy5Asu8kJK_DU>M#!ed`Zx0i!R< z5FH3-YeZ*%0AHeSMyX3%`M>4}DfCUw19@kreUQ#f3(k_>ip$j%y6;V;k6%iyU+QPd z3g(tBdUwA^-9Kty4YyrUgrc#|GXKjx=iNa^(H_#LH^_12-F(W82_NxTx2%4UVpvkM z(s(&n* ;H&3_u@QQ*a zf(?y&1p*yV5f7?Pd1SJ6>COE>{*Emdo_0@~uRyzNDDoL!;0()mn_m0cr^2LNMF^o% zW)aDXL9pnz{XUU(`^rd(^?}7+* cArc- zpDm2&o$ i_+9{*>;Hck8IpRlt*hbf9Ln zg^};g2mCg}1hfycRnzAHK?493z=FG8D)}2Q5lAGI{%KfefT8gKR0j*e76U}~Ga%mc zmYaMgn)G3r-+A#2B-eTc7G{9zfK1TGU4YN;KGYQ5$zm7*77e=%anu*T0UZeR%EnUW zOWtKQ6!Ow7xhXfdEDw^5(jcs783hC4S3-tlwje>)QMUvJvAsd?X(NX2$3`X4^}yGR z9-!GwK+E(Tf<2X|Z?DqyDLW8{IQuQ%Ue{N>GgpB#^3x@`DCoPVSQ&lVv3wH* 6jbENI%L$qL1Q77+Q8o&CLUB92o?V0kw) z6Imfa<0%`moD9ps+IG;8;JKW9+2=%~&W+mX%a8IAGpgyY9m~^!Kb+EpTf*3ohv5SV zN>B)wk{|!0%tLc@2mRK4A;+uAM>mE!Mo$VK*nW7V4;{|C+smaJUm>D5VQZCz;+|Ay zz-H*EZ;GlJPTmv`2c+-j$=i5Ld;&erp}n~Y3Xzud)OO09k;Q8exoSmqROK{wadrA^ zHRfvT yDpK(Gv}^p-NQ|tF$3N#$l~v0_TYTRm_lel(M6xMOp7{s8H*}# z_bJz7%Dx&~!_>s*&xxifc;h0&!;3Fiel@j+M3mXe*& 30&)pM|U2_oYg#OGR*f~p@sQ+}!ep4=-g=SSPU&UM9t%4-RUr+MBy5d7Zu zK#%l>ZRwW~IFNGbVtkdbYWFnK6}#Ml1&9+C05Z(nQIe}4po%dgw2^P*mmvHm$7sE4 z|M`^T)b&tq&ME)EaJ>7pg}d*~o~;Iyer>-E*ee0THT);|CEEoz_OZnpelukDZAg9v zO~U#|`&$4Az`fpcNj7~D pnAd`XwR3-e)@y*yOk95-*us( zi6ks3Ye1gI8W&qeH;$J-`J1Odtm7i2n-Bkflb4X{7fmf?iby(Z6hQpf0MOvWh7ifY zCoST~i|wyOb3&On)qZ77#H|tLiL`_uL^DDmwixK?kQFy31C&mcL3s=7t-IVlnIWHE zptfrrBgOQ^`y-2sH7Nupm`T9kh86Js;mvVCM}*J^SH$z}=;@lw3|jd7jCc+ YLlO gQVqxD~MCL11uXvjr-aEnuYaWXPI#< 55sqv0e|o z3bDsVaaK#nUtM(hzCI!Ax^&wpm9B_Nb0p(^4%2d##t;Z57ic_RH6%JED1F_KWs|zi zb%y`yg> SDKj>yy+c%f%gbP0ra~aY^@CH!igv9`=Z{d@Dr%#HvD04{-^tuN zsOJbM4-~+ZcaG3Dxd%4_J?sAP-!0Dkwx2axy9yr#-CjvKUe|Qf6a+ki^W~Qd+Wz35 zl(~|hm;mLs8vu@M@7d$0XMNOi`=fiHnb3uw?YB9XI(2`~zGJ$WzW)nca_2n_aOX1g zjpk1UuRlA Kk@zWr~R$hI)%vJ!O5$uEekLIK(8yl zgZG!~I$^J<|9pK1Ok>A5upalYyiATn8#?CHG;lYUo9kG5OHWiic=w4n3Er!x&il9y zpk4qmn)sZ&^7QHXz_OvkrvHvN;r-w}2f)&kOoBjYLq|aMCN27{Sc0d-^qZ@EU+FPl zpvL#}D^HZYkN>^5YecShzFJFV_+6g(KBVxw!|6Z$#1AFm*LTmK>y^JG*8gP1lfK>m zo$CkldWVy<0Mx4h38c?WN#Bfh|9;NEBMJYSc#t&4+Y+r!T~BQ*`SzG7Kt B3F3g31MrXSOgU3TZW7N)+a-*gC@cjS+%NZ{O6n(ZC2AnpVmV(N|KS8^vweDBB_ zDGo#}Pru(lOHjE-^~Xnz^hVu{!G kH6JJ{jQzIEaOyg(&U@0p4Iw33R|T zQH%^zgoptj>LTi8OiUe7fNZd5~Dt&BwkaI*CF)l|+xoGcS!z&nv=(kG){rQ;OIY z;n>(GZffrDzAbw~GGZHqZy6<`O}N}VEn^**qXe*Vu8t8d6>;FPIM1`VlR7!aO|Y{X z`$t%; CeTvQa$&-bJtf;rIy}CO4U(1 z-`OzV#UtO%T0nx?ROoYF8+*E|fq0KZfuCVPfVC%;AULom51FlKKu2Sw1`3oe{AgGh zF9Ft)#)KCsVv|y2Ux4E1in62&Ti5lis|#Td^B67*ud-*0N<9i&UaG7_i_R3L>Jb!` zB^5Us7FBrMtr{rgN)oLvD(;dlYMw3Dd&F05&1fVQ+I?A4^Gd%pgqO6xL~prdEa{VO zJlJ!fpdm|1%sN}m_tUIl>F+!fVdYP4guo(qsjO1zTG6M *6N zl_h=!vs4$%>KbkQ{3L$&`7T|7T4&iG!_uou@S?b)2*>LsjvTR`XZ1ct>>tY>Rg{tb zsu;H<%u!?SQ=?~uSE8Fh KG1cd93Ob1M4IU>jZo2bT{jGCG2Qb z>U@$Nt{lw+-qkZp*Qq_Mb4adNsI3p%ejN>eq42nY;A>5SjhOL4L&mMfESbifr;T|U zjVZ~do*`9S$<-k|5+%u1PdLmf;FZ)&FWsa{YHpSF&NgIMHIaU6Vn3C}e=F;Nn`#v` zbtix7O*Z*agdV(Arsbl4K-Ur{-QxAIWlE!Pnnz-`sU>i><>hh9!qWo3Z-%3T<*QE% zd6G@ldPKIGT4QEgk!w%jJZ;_TZAcEY!_YSWqP8pI(^lAWTh~^jAjk708;3%;3Aluh zxVhm;&tvl6Z{R5=onq~KdhNt C;#Zo%?yGX%u^H`v0nM;_P1U*2OI*6l0Z{SwjR z@V&>Wq}#=_*U{F~xuoaaP_Oht4 FTz >p8ej(}Tti zHt#r8(-X++RmOEzx6uy?3l6m*2zuxV`cj7Y%ZCKVhDL_KW52-@vcudu!~FKc(?ic# zJ%$>;4D)0R^Wle=o`F|ny%#-4=5|sSeoJ&|4sJGs*M>$|1V_1bMo+^=xiUs~hDOl~ zqw9z u^(Y$>=|RzLt|_UW0Qz+R;KY0&2bi!@&2%JXvTQ=@8O~5k<+jd zCWc`axrq?Ni7C$sv>iadJAPC$@oi`V{bxc{ZbF=NlurvR#V2w2dqD2F_?=G!3U*>j z&j;?Nirym~P#YG}XzAD56~1rRfA!#fqD<<<9{q&$`!D=_ldGPSzjnTCHGg^X{EPm; zm*=TpIJBl@?51XgzeMd!_4`dZrlReK``+>auJ8NYTfX{y|H{gj(@QuF#XfzLG{kbI zb(?S+255dgA0WZ2H93!(X^k$*&OnhfBeFjJp8zVzG>M5iNT*7tWCkiYYn2+czcZOA z2hJlMAOJKa?*#`yW*u(MtcfQ0JOfC|9|iBu fEF$A{AXtX0GUkwm?IU(QV`6`&DBJsNO04=gg_Zz- h^7z6~car6se3b0~Jgy@&8@omuH1KF44<~#Mv*= z;Ff7{AlW@D{#HV{jwM0)6`@i#IIt|229k~daT+akI4(=iEi22fV#wGO $LT- zr8Re>HQBV~gC2T>{knJBx@DTYw>&pCZNsK?Me{FJ;K(vAZ6kC9{XSxS1PqO5+)y{# z&~n&FC)-Sn;JQlwySBZwnVYtr`S%6{3;IO1$vwwb*t$mIv|aUjjn=*u#=PCcxUnO` zeMqrUL&g@#xYI1Zz6k6Lq^ 9lpR5t4bvji-3R z+1I ?cEs9t z1QyuLYNd}eS?3--5;flP Uo>-8nTkKDF>VwM;*?ZacLlA7K73 zKqUYO0bX?g3?u^sz%@WM`3Imzs1%j Qq;Qv|8r$f& z2m&7VmADK(R!GvJtscNTj&7W&t-6tAMmcI|mEDSsB6M7YjqGB*1#CT@k~{hYhj1a> zE#XLukQnPQa%WG4kIB!W$oRK#ilmfWS44&joHQq|R16BC2u>`k73Ly~A&;tSwL$ua z1h#dvLJC7_dRn1m9Zkrg*1o)|$+D5LkNwjr&>zW-bGhwhT`M1<5v91zt;PK#)q>B* zKBK2+*o!*EFYNTpB~f_<{s{zL)UbA+nIV9Hf&aUnwSr>sE3{)}kWhG!7QKuk?JIby zD&J3|D>a(8m8&pfw&yHT^$(JUc!i|Y1l=c9#U2V0pA1c8qz-4^(|v8oMadNnMa4Bb zsqZU%R?{rB@U|BlAIUb1RNf#_1*exA;-Ye2P_fMB= rSk2E(Nua9MGq-(b{{@k9fvY8)g zX*%0q=nTDmzqR?|cw@5Ic(k?U*V)1HVEX;G)<3_l0qXo{TiewY07WlgA!%5QH!Rv7 z|Ij9cePhA5j15@y3nj)Z`qSjGng-CjY%B&c1)!IL*y1dgg3);eOCh|qFe6|79`tgU z=v2^mKzyxWIYRbyBb!+8FM0*1Ol4*60@8tDNd8Zq0RXQuKmcR{zyHx06VpGSK0C9N zck5rBv1th6mVY6krv5y1k$vWxcQ@`bM*2H9VpZr7v5teg9(TC|SQ~L_x5;*0hhHZr zgriHhXd3t3a!FY3=rKdxeSC#ADPBH>Q$YN}BTS&4Hsl78ajsAZSx^izKHWGm*_Avk zBVRQu<#n!iL78|IxgVmu)<4=Ww62*mF)*^Ur4yPR0T1hJfg-BnI|j hmXOOE^JLk^n6JvXDbyN0YjH!T-RKF4Awv|34j$liP z#_n+3dMk75^83<6G$cu>WktlA&q_B&yUwz5BVc`^fHTwVvG8NF$xp_m6w&sSyvfC` zee%dxQ=t{rvfZ_Rj^aoSJe|HF0gL!osm&hbn VOe8*Bdm)R`(`Ap)DofTxm%Npj$mya8m8mJe1+ zUlF`a4=niqzyvM+zvygZDOB*kI -@xQA>^Bg1%<;tM|Bdk`URD1eNg70!{ zuEgjtLRQ{@M6*mk>RW7ni){(c#>SZhaIGbn$62i `DZ{jeq0{xt8nIKXP4Q`&X_d-v8T`22i-=D RvFJ@NbfD$K$B}* z6tW|~*6Ot_vbcFzdxb_>hQEuBix+dFh)qaMvxShR*dWvMM7bld{`sHK+{h9vDyX!U z3sLDqR##h?U5se?1g(gw?#wHUgLm|&b~lFBjK;Oap~#)SL_;B;qv6fpqq^}SeJi2R zqUqVK5cgCRJomt7K5gmDr{Qwp_lBTk9r`(5nm~?Lww_~A)(SB$+4Yex3*)l^7_JB( zPIQFRGgHYzgtg>DeyLx%L @jno~D8 zZ<@C#)ZCvdG-UgdZ$+(oX24!xvV+U`i88E0IUjP`T2dAYwB&)KIlPnxPcRsMT1# zIa%=V|2w(PtK+>vqhy-6D{4?P7`!pt_5|R6zjZ)(a{CE^cHQlFuxJ3&@S3QoSI-Bj zf?o8a HM)N4%c{Fyg*kDEFcg<`*!YucDeL>l|StpD4U-esI1AjJ@- zOj7s4nOFCfd353hZ1tlk9U2z>a1Moudp4VeC%x|?wGw?(oomg+JZ)1w!C;!^d8~Cu zx5c$w8y+P|nppiK*M_?>AE4YD8GcmO8<{~IMH^XR;#(Wp_;%vWoR4N%ubg1j8Jl@2 z)^y;1)l38M(qAWi|G(zT@$X8Sx7b?VKJwp{^qnRqB1mw;9s}b~bL_X3PUoX$uGh~f zii9accRkt`(iW*J=IH#&J%&%!naQj8J5=lT&zlFj(Gm fAZzWxx$g9HE!jBt|;={+Scb#M1vbD zrmgpWd6pd<(Ko6IwfAWno05Lf HTGXm8(4L`^ef3TVZ(e?h#G<;J2mY zIsWSKt&7!-%kE$Kkr;^j_i74Hap*h~F%h+)jec;7asXr}+{tZxiYEL_+6 Ex)?kja)_RA0A8Qn9AW&BSkrX4I&XMJ}{}}U*{r9 z#c@GYgznp#kA{< Hw~3_2(K?GNDeq6|uH_w7j&Ur97sMt+Q{%?6jtcwoe^X zNmd2!wAaEUgu>3B(ACRS?n!^2=2{+zt1|n`p%A<_ye2)5LrBlBQ%2v7=SXP$x%uUv zkbmw7-c5kp&eyUjNKnFCT_q~Vn&9?}vD_x;J!P=}LLU*AF d5c$5CE08G4ST$sK6c$^D--m&4SS#GdZnk*52jkRA4(FiN( z@I^OUD*AA&sARkIDfTgu-rSR1i4?Id@ClJRfGtO<@;7u4>J%YaNkmlKeXv~6e)d3g z-a>X9r#{l0MDuTc28nU>#a!Z3!@9NT#}k$oq+N$PD~K131|6v{m-Oezv{44@A=tm} z1%Xa1(|O6k5x6|E+jF?w^yniAF0xq1M$4e6*Van;QbFn#S$U26X!1f8V$0$J|9%Kz zWLgn@iJ-W2afD$~Fb^@^)>c u86M7jE$R%a~#s@hgJG_Z1d zt-y|HivQaJcvM$Wp?Z^W8}6`V OlYRch+U}6C4-D>gJ2LOmt1ToF@BTq}k zsCdVANFbERa$*8Dygw&dF_UfNtpWA10C+sEy^{+Vd&6{der+y*Boy}}jXP*(AMk)= zm;-TWcl%p_W^+)hJA`TD9rgU8Q;0&b0|p$<1UNC?3Dpt3rS$@dpERKyQ|(v0r?pR~ zbfxx_njmZlig(w~`1#e?S*x0fK%_&2(OM(ql=>CiQIu6f#IEDJF 7x&=0spu~Ghr|ufzbM+-0$=?WzCGT*bB`L=^ zF@7q`IA<_@sEFNs4nfMmV~)$4c3g8>Rl!W}GG$1yx63;BxrbU+MkuN036HrB{&*0N zlwssZz7}UTa7L`R$`Q{rr72#lH_geA&3ids2rMi8)%=xLvZwx=rsU1Vy4vywlE0UO zogk77k*Cx9H-O)S0PHl3Kridv^fBR|5{1UAOeU;KvWf4 4%_7Vu_K2DMDCJrJ??? qfYcI!kS-NOrM++9D{6E^oST!A4n62o AveHe`0alJ;rl3CH&jSx6rzj)mok=Bo``8y+W359Nv1^$)-HI8I(btZQ|+f**#& zK#{VXWD|uWE{(^j>L)&YQEJ+5dHBH7p>@<&;pm6UDtIGryX@USRnGJMbl9#1=7u3b zj#x}8!rxMn{gUtlN3{>a-%LdV+vcTf JZ#zAzs{TBH-G{#l)>CY?&INH>1qbDs3i!V4y@NBQbsiVS}i z=?@p_)eU?p_4rwALRzfft3I{Zy-;GQWrI-sUz_?*{y?wu=kh=0|9| t qQC0yS()7p$Ghf{iIF9pJnv${qV6b-;fKSO&b?C_e$uGCv$OSIhnJ6E+|)^f*n It9dEf^rsTtA)lISHB`tqHx}sSh)+{rFf5 z=_GYL<4$w#p)GlT%(6K5{x^~LtYYw~qId1`4?J9KCu*M0&kZLh`VF^u`H(Sg)g=(t z1}imULFbh4tk^cw*X{0 5=&@uwQb1)Qny`slWmmxmwAio zkv)N*7+b+&Ak`Koi{w1EoH;~pr?(>nouI1dEI3l27$~&%#K%)gg*l5vVAkXXu_RRO z8;* xtD}9_ZK$P$t4z@H35C(RFz^UL3z$3k)s^lUgE5Z&Mm^l zo!#?3SeFXsdrKs^=My_*^=FgwMbvYKd4sv{CQJHVyvkymo}o*$`CSOkVNo?C$d<9~ zUyV;H#dDEoauZt>qA4%^@(~;%+zB7&T+t!kt #pvRzD$WABV8TgMkWERveW+dDmk2l^DIp*T0L0C&6sntb z@I@qq2&@8#cuX+V;G(8@NsgFqod67Uc>qu>gAay@9cy#nN6mWS0CwS1DF{E%*1Qo} z6{k~S;*ThBU<8E;I?@ucg$1^`AGjUel8v+N11{yW9BF)wLIa0LZ#iOyN%o@_2hCRo zju~&??r`+tM5bmD-`fTOWB$Ah_e!-xy?-)`D(T`GAGlHndr5bW|711ZHwC%B+#hn8 zGEMn(!b*wXRRKWL3=&^dlb @z`QG;?oDfL zn@Y~U)-fVjGsmX6U(w@~e6TI%Zbl6^;=VC85_=qDB^jdw52cCgk~5@ y~JoS`0^xhXrK3Q0GjLtu c~Kt7}1|O z!Gzkxyi{Rb0G_3t{%tvARYv)eQUXg QlX|AKj)uhnU0bpnT*sHU4DS!ccCFTfnkk+FKs4E8RTq8gTpaJl+pu0Ch?s+97 zWCB7s<*TE1`!H5?HnU5R%8kA^o)2i!s7FPyj1kO!cFhV5i~0notK-B(lPuH^b?yp} z97eKX7+R@nL;cyAp0fn8uyCsNs~a9gCk*9qNc8t>dmP1NAac?7)CP2ujy@J>=5jyj zAJA(&ihXg;$opzDfa4%C&NpY3I3u4xEkHN!J`A`m;C}b{b^Zt*uCkK{gN;~32 LL z((*AWqztKYcV-_Ll2qsPD8J$+4w;B+bPoIJS*ZC+eKKkGBu{d<@H&4c(}Y!X*JQ1v z2~GU7=zbQc%2~ty7b&FwoHYML%AbEC#f0_Wlcs2~70UDP!%r4lBqGSZkE!0RFX#HC zX@w#0tth TK69TkNse{OnmtC zU(*v-67#-@RlTdk>Y&Qhf!H2py5F#>_#stxn_1h$s95bM6r|#p{eu|!OtN6`r{1ye zV!5AQLr;in9_a)q6;H4*J(#J?H~e%I79&zpoc)6?DVII={!C3?n9Fc375`X;DO+=m zO)M~}{{?@ }(cjr=-p$SH9G9(A$Zmz~RC) zM}j@3^efmlML`HDFpx11`z?hwAe2z9SM*?Gv& VdU%2s1Pro4fwu@E@mt6?*iBJsaAPD3-PsoblXqL=D+~k-s4V9s3 z$o#0LID?5T5$gAer{a)I3)Pqf@?u#K8{bgoy5$_nLXK)L$Q&zY*uq@23kjk<;!Ng} zW%*~;BbF&hvQX|&l4V%P9Fuo~s_526EUB_#r=J#N=4D xa>*Z|BG z!B-ZY&sCiC_}#p%8M=skVKza4 wS9ET%K!Jth#6ozx8 z;nuyDDA<|`un %`H>LOUYmQOpCX<-dalUo=x!da>)+1`P)-GzX5}6gh{D1;YM7$9 GVD^8>OF*0kiziJR1QBMwY @zj-);Og_aGNlehxcpEylLm#Vz@7t+?VJ_G9e)=rh>CinV@}0R z+&|sEh?D7>pTNU9g(xcnA~h8`E6)4-+$$p0Y39i8ZT9mU9YPaI*tm(LG!&+UBkNMW z@YrGc)y1*FeIe{@yVHKpxB3%=k!wtkHwU5RsL)Ycj<3p8Dlf@&V>Hn8;w`G0R$JrA zoEVN2faT$0>xY@kUw5!(pZ0ljf)bD%@k@}cV zKt=qEoje8Vfw2JTlT2iIfikE1c!=SDB88Tq=z##sjp}UEp;wIE{VJ^I3pr@5Lh}FX z=|Oaz6Tkj1r^j_p2>vf8$`vqV_snVhkk6X_$q8w#GUJts0>iSbpu_%a^d(E3t 7c970&AzeRrj~^xHlUb^D=q4}-ItkFTW%l3W`_{`7ixQ1>7Ux*vj#j871i_cVsb zU7sE-QSVdJvkD@TbB(>c3(H;jqir0J74 )ZVYvR8j-48yJ^1 zi*XB?n3fpw?P;5t=av8B^L1g3(`>jKKDWL{Qx(zEwZF%|{Qdmrw8z%e&M*9Kqxp~m z{>>rduuQ@*p`80FjY`u!!K^NGO5&}iAfD`NkZbC0YmP8ieZ)$96)Q{2%PtYhdza2l z6=k9M5sKiJbrFdNSstbR+_A(Pmr0fdgg6=u<>~4WKUN>R5RC;vRld*==zrk`C26(0 zkp2|mN%*we!~aKpq;OXAWwPV@P{+~nLbXlBmnP8~{nZ}vN9qqzmL|n1BY&k3wmxR} z-D$HOzvr%S^{a=g;d#T4P%l!NtmPM_s=LPX-dWG3TrO;V&3O9XeXI1QK4&9e5g7VI zlS+Sqbl~g_Cl&f5$6VjJ14n1P$nBNi4JeYS{2N7S3=sgLvqnM!M1Sx6V5u-2{f4#q z=w$2b_Bp?g+;4$ScFhIt4tcoV#*Z^XFYfbvMeIKDboUjZBuzczdsfK;CVI#K6EiU= z1h?p?ZmSRWRmV)<4%B)i>EkTn24f7?Owdoi%@SwN9LifC1PT!=C}0j(+dzXOL{yQi z?y{vOFG%DEus=wMsT$^@IP`%Wgj$3SdpHVXwfgajG_fO$*TUW8hT_y%PRxo`gD*s5 zt&cs@taifU-5ayQJW|^|``pwI!-<_~rgQy@X&S1*93&3h71(%b8V}1P1{VcT0vm@1 zL1uK) 0v4Cm<$Zm#?xTz7-*+7RO@}%uxd?j&*5dPOwq_PY6$siW_v{%fTrG- z_5^pixJe$~AYdvUXe~}FFQ+aCrv%_{&qp0Zz>) wy;q$rO?u)SCNeBb1`&)0DMPXu2)g0=Sh zOumH*Xjo0!_=45&e7-Z{G<+ltR*-|r?=lel8LLaSBBpAsnn8V`9KeMxwp%i2fS&~} zi7iLc>)>a@Un#k>hImajpuKF8;a5vwXiEbVV^xsQ4_%2x*X?o 0A}o6} 6pOu-MCbr>9DR&Q9|H-%Yybe3^ n8g6WSuI^o$Bt>D3U97yRltWPA@i>ubHi39G z<(FAPu^u~YWFIa%AIxPW3=LV(r564NecjLDko1-ua!5K(sZ->T{@VW^^mP!HFT1Wb z>M?tqc0QCZe`XMwU=S1i+s}*;I_B#`calL!3i@~Qpapmt02t8sU*9+RA95=C2RW7h zck+ rp_+rHam z zR(SY({o-0zcRV1A?)duM9cUn~;AD4wrVX`yIdBL*S2e |^hD zQv8;sM#}57>|#!1sy-SIALld(Z=sEl-@-gIK5ub+*!=6Zn>fbRS)oXZH#jHfn<+7= z)pi=Jwh}IIE@P>ws 6|xgQMgXQ-HB$0#hK{ z=O-QSnf7$NNmwSvMgzID$4!X&DowJ8MSA*_BG_>C;Cra8dV g!b4oa83M1^$D-?Vo#Tv6&TZobJXEP$bGx$fe8$clV3AL$u_GlLYz3!>i} zV)E(wt+v(*Tx3Hy^85;latiVSo@}L|64Zin{MZlZOB-|!Hc1H)Op0JAjsQbe+oNlo z&rKf+1{VSLn37H^o{+1m*-z_5Fhc#}{%RMtcSJ?5nBw4a7f&^C!&WSw{}zEP2dw_$ zEiAa+v@bNUdNb{SpZTh2+>ULdHnX%Tl3r60@B @<5be*BO$xju|LR;peJq-4b6Bn61n3^RBMdJgZr~eH2sH# zh~+A|<(D4-BahH>)!ZugO!sOO-YJ~GRNn9%cP8iTXnj$N`JprfcswTqwC0~h%vLZB zJ8?V_A^6E*|H|Z)iKtI&_y<{*+}YRX>T-&6iGbYsQrJU2{M@o)L^=R4VeymMnl@5E zWG5Hq2d({w(koV&vwYq(Efa9gK(t})v+ 02mN_OW!@wngI$^6 z`nv;kO$q}0T$H$GM?0rtiJJtJNI6h3d`6nAk@3LufV;rRYEb+czv3w?CD2G({)9x9 zi#UUP{WPiMe$~8N*Ss6F?w(imZ`r4e=S5gxWmkZZs37gi76*K0uqT{a27yTMZR>J^ zp0s1Jhx~o*WF7~;Oo&X_J=G3W(t#gZGn3>=Uk6p=fxlo_CgPQ9C*ABpfK>f=sDmVU z?eHK_cA6P^Pq3L&ALk%XZ#G GBFAPQh*1|vBY*h?3J@*Ec^{m$`(dP05xB#Zh@ zLH9JjeUyWK$|Mny<=xHLLEo1r9klCID%_u=EUauz8NW=o%atBP=mKnH%aV0cdfq+^ z)yA#zs@+_os34!_OqMfhwOc4%lAzxi%$W bYftE4H9I_{q`#ju&P^0Y9iv+Gp` zBc|f);kJ&Hnk2 z!t?5($ZNCz8&TW{%hoFU_Cyfo$!Q?DhxN7-B(qRQp{#sD!|p>76akv=?}o?4iwJla zzbAW^a9#3~LQ+1YXBCF#*rXN|l{*U{a;;0ROTGYv;%#tjL;LfjXxkvij{XQpja}Wq zn3RB*YY@59_>5>%cPlDwcF_&`89Oz-w8 =J~(9xp?C%MKR>TEgCMoXzfpBYz%K z+v!O-&BK;hUCRww{I3wAmK%G_T|Us0-EAj|7fl#?8SZz7 kE2C%$O zmj+%DkE FKbnOuTv!0N1C7pjRixlAw>KOX)6#V@DS`foule~!rM`+#lAaogr3fW#(7_UI zR2j3Hhllj`EA!sJbMgD _iW0+r*8LzizcXcA5zj>lrh9jcm!}YK zC=@7pqx3cwh{+8LlmjykpZIt&@`KEXIcITZ(7o7%j*x-izKj5V#ttQ4fvIV57|&P% zIFiMrfHg!CCe`W3i<2~u5Tlv#fk;*YD>xo`w0ESIWCPoKdU2s#VncrSrFfaOjFq_O zsEb9iS6PK?F!R3&%E_-g8ZzH%C>yM&K3fA`-k|hT%Y`|_m1D!kcC9+z`p*&v5b8Ht zDrCbqHt%MH7+Dt5MOh?yL&CWg6hbY12KoxpvY5~e*)Cg4d4)zk1>Ep@kDFj~1N+=- z+#{$6s$cTi2B{|~w3p1_tie!%ArAnE%B{k`Ek{)sU)>;r+#;!%+@*X-GUKzv!vr#k zeqLiskK|KdJ!(*Wn<)&!g5tuyLEU$KP-Q5hv2Us%=ap@KCioP^YgPb~Vu9| &pJTlBB-iC7W$!}7SUH@ z`|Ql?ve>pb`|a+&_-n@>H=X_t1IfX&DyUWJuqV`amPOy9K+561Q#{YYcN=|Rq 3Fm}4g-VQutPYqOai+ueAp36Wpz` Kqz@!ZufIi{FbQp~+7+oR}3_ z(GR`Av&;yNA8de56RJK`2Y=9e^R?ojGvysHxQ~eFH*uqcLP;$b8}hyVbTJ11eJWB| zsp>7iHW);RzVEvUIFEK5hHR0ljIJf)olEwfvNR78tlU-wO=>*8G8b<&-VG<6=UEsO zUbw^g=)O0bDjpPr!|$#lfRSWS>1U#LI{Q#}6^ue3?{xeByV*+)Ws `{504^tQ8pu9Nf1`t!bWoLyg>a`tr8Dl z#>wAUx!l3^urE4TayFY&b6Y8CZ^5D$MNFw$0QLA-A%yeC91^j9$bGW@SS}NDq8pzf zN|$3%Bp+AFY=iHVRG56smU($Yy-=O1!x2*QD3|5Es^<76D!8y2#2?B9Hq;e)CoH=r z_5e9-*LaYK*~yb|Fd24;22$8R=Sh9-*QVsHO8sxizyCOE(yycBy5#r&YxV{IfkD?L zAEvcIy%*e>#(o?)bc2(e-Ov~Lzg6IRXl4M2{}0B#!ma7PZ+ja9wgF>wN_P$vNpXad zA_^iPNSB0^v^YlhK)SoTOB|gdV1S4+Qc6lnKzZkNUHAPw_w&Z_{tdt5IKSubtPg?p z|NIZNN5r7xDujPX=+m3<7dq5lkHg}z3LaEZcO5946EZSIJnYOJ zsM52FigR4@ bnd~PPWIRrO%xjnBfqilTDf1iY$(vO;&YGA@0Oc65H z`Szo{IAY{o@61;jz3I@7h1F|ApO-h*w)vi8SH2%`>%EB|JN|Jng!7L%J15ugY&ECF zJ>BIRkh9;prHG+qGWM^ZKqy8+DD+uRD3_ZVeqB5}JS8tGv0>4;JdiAREz-0US!@qz zzrU YZ)mJDG+H2c?p1u<=IT~P@7d8 -!7#M+fTEJ zA(vDXAvwqx8DKrP;bXcg{w6xbx0@t`bY*H)b3rDSS!nCykCrO52uq9VT$}UO*H?wg z&RSg#4{&>(kziQQLkfQQ0Eqa*2)n4=PCw{qJ)^{IH>gYeSYfVp3(ElrKH5#_jUL)3 zmGx8KocSyh4?Oc%*k66;8sBsNOZ=k-QYrB4&27;0%XTIFC3K(}ZT=iuGmVF>Cg9CN zUd2A_3ufF4x9|`)nG6Z%);?XdLg(QYBNapp%_(>i&AFljkLs2n($hXFaa^-%M7|`O zZ6Kgn3C@a4B4aNLtF(kK48F!X!ULyQ_@o>vIxfST6wQ;4NquymcrDc+Om;9$NZo;t z(Y_{cEyGlDpD(MVnaL*IbJKM(z-LXCJ=6HisL#!6Td*w3FiPTEJ~yLWK_O-i3M&*+ zudvVaG(HO>PSb%3veAl6@`vTp_m vcz zI4jUzvwpxrl{~U5DG~d0s2KN1y^X_)!=00c%nvmh8t_QH&r*SPWQ2O;f_&Vp%4BpX z9zU)OP^3}$!7V0l;Xw)GxT7+8I^EmQs2z{JMx*z%_iC)#jQf$dk=a$x5x;d-+nG#q z>=W5r{B2URVO75t`|dT0p3HmB#0CL;YBApPj7t;%5Cnj8Yh~oX;sCz2g1ArI0Gu=< zU>vCoihL@F8U+W44gy>_UDlQak>@g(l(wa)pWk8%QE0pipl)`hu<*na%A=Oh0gL j_P5E((XYWy5=s^<@H3K&X143JBLX@>3|?d;5&9a;RqcFiiih_l93YO($eFzTWT0 zLhuWJn({=mKqx7Br2-r}-mOS6ocp5r?8mp-%ik9#yM#bJc^-gN9S36GLqoLlKn%k; z61lw~L`)u-KaGZnhr^k6JPR; G| -JZ*?%j_$VzWx!*9H2C(AeQQ=m&A;j4N?-Lt3CE=3jLYsmH4`ZSEnOFK&2 zgq ob?{ z-tA7Q2545u66s7^x9(#Hbh$#0Kr@8+p>kc)R$p T_}zyQj3>HPI!I%ZdI?4$Djip7#_j@ zQG3Y$yQF^w03(3>Uu>V_Uu?f>u>%a2Z3 Dl>v^Jm?k$uc(Fy~jyNf{MkBu=!JK z7(+$vi!>s;2Tl~td~1)7J|`AqTWJc=dELuwQD9AF@%|DWB;ZK-kWlT8jB*!;`-YLh z!O=;{ddT}W1kiq&lA9-tq;km2&MzxBR-^DJ$*HK1ij6PMs%vO}CWdHs_fPNWwHG4~ zMTfifjTwqlb$f=ljlWmv8VbUF_^ezQl}Y(-epzTHdTwQ7mE`TWtj#^Xf!T$K{S&dc z {ZNy%07acUVGSUVFMwQEuou|mG?;X_r}AA2t6S5-n~TyUr7 z_NAEcPiV1bB8Ommz(@@5P|`JzJJ-@<&2&s@gmdPJ_De;=l! tQqT0r~I~ST5V1GgzzAgO#Uw)4%i~ zHt>#13*}6c=>Xdm8E-AJ&eEoRf;LNnHxe=A5F0z)$E&1VeYkq@lMY6kclYu(NR|!? zLfS9XG=+F``BuF2wqNQ(Y)sEIKD`-8OiXpM`nEJ)t}Ei~>{lYj|3-hf(o m8A9U_0N40LT%Bkhwv0A9ApMccB*4*m4p=Qc4R(yAOmnvoU}C4dfBjuf*D zDu5w#_V7^1NBdq&?)eB%^bHR6!gzTOq-xmB;Wki$dJczmP~@$VV6ff<&;}}RTn }>ab&WRP%LTJ#(2xX1D!04S<`D@Hi-2lVc-uOM8}8pbeZqW};=0Rp6ewB4 zN|u4FE9M7_M0BLkYOD2vDtmWWiT1Q2`=dmhZb!h$3ij`EvfDui5C)R&wLsk%VP0YW zUI`AinR`E&B*-K^YPqeQkZ<`> pm2EIp-v280OMB9*n6G83qT}xy z0w`o&SzTTB?%ZePkdY!0sZpQdpQL~+F!{#zE}l<}{+u$ ~4H}0&eF*C1|%Q6*(+o|e!j#)93$&rBq`gL;l1vt$8nGY&-(LX*b z)q)OC3T)So-$Ah+hY#@Cp#8eI+FqWXgS>9on-k^$q1QyQ=LhFHFAjeh=f(vsFLI?F zUr3`jN0j`2KkE4iVhjPViwE8CSvcDaRfND6gZKgTB%=SH(vA`qPeFl_*;=d%lribq z!{nhUDiDC&%0)ovqzWxFAb<;50Lh=dN-I_$z~^Mi ^;z=;!>EfbqnpL_G(^-r@ zt_=RE6Mpl35H`jhafNiio#sJ4%^^vik8qq-Ru8rqx#HwGq z)nduVF&st%YSQ%Xq<%c6eD!<7`JeU^dD9-Jn4ApW1i0I0^I+I_^)*Ver^7O{EV%eT zRT@%L5!HgTX)BSMx*6sPzlm%S1|t G>TD3)4m}Tcrc+<3u0cWs-%vBZ3=nd% zk*daxI~!ch;15`Xm;LOyt9doKJJ>?{6+zOEL!~RZ6C`~j*?&v=|AXznr|#G0RCp@$ z>e)2bb**bf%27a^+whO|TL%1}55ma*co3W%x?Jb~k$*(Ak>qMT2LhH{a0nLXD3?1a zaCqx4)*sSuu1R41j3<^TE~7d6mxpl+d#CSFZ6$7rYGAJ2^GjiIJ8yYkxC=Tm%F6TM zJ!a>9e4qYn?!C8G==JP4v`8S&ZqrDfcOPknRBYm>#(-F#oxwW4i`EC^3VL|cy~ zk}?nr?;YtQ8GcbcI_W{)S=Ei3nw9F08v6A0I_ACWtHg!18zfXo*qU!UJRMuq6f?VP z4NFbU#~0!Q$=j!|3J>l+z8Z8wjvD3 ?rNK;T!l3{tjesU>qT3Ub?{YTMD><7Isim zy7YzIzL!U{pUhz%d`~}*D3~|zgd?=Ex^58$NJMgmE9{l_h6|2|b46Z_5m@l2D!_9^ zm!GzB#R3GlXdhpT!YxDiCg{0fD#vZg*sB~G9AURp@~mMD$dTUIJJWkBko(hnh4Byg zB9&7_MG%D)SG@##lg(>5O5hXeBfT#jO6u0&&K>2LM7JE&D)iZ0Bq-6hyPh{zi9}90 zAu!IOAfG-)a3F{0fI*<(o-R@#I*dMb9Ud!`Se_mCTj@*b4b907{z8{1iXx(njF{r0 zij3i65n3b~0%gRG+g}SAWd?QhV$fAQv mabv64)SR(3@UA;jl ztk#_zzs<6s{64!yAw>9gvyJJ9GwUG6UDRY#41{hs?_wExxq_(|WBuCkS rX{Z N?W5RMW$*S@&kj}8Q^X@hxXmZT-*Y(rgAjUvZ!&oT|dVx zx(V w|O*%gmZF3>)Y9++*qh?;KWaNQEUN_N a}263?Sk`qkyCV z7!-(Twz>)+;axQhjEvSrFIF7Hg7AUYbb5h)FC*GuGq!;$3qk}6=?OjOUh5IM&& zw17s-i)_ZSh6vC;tt(SsCO-lCw8n*%4~=zmaB~KlU70 ;lM?vV$M@nQK$B3g nY~SH41l)1! zE6oDp*4CYU3gwv3bVGn1A!iBl2Qhf|Ud9`5_^$WFu 2f)=Z!oU#2p`2FH}LmLrU&u+AWeG#{` z29ahCWkMDYkkuhi{lP7FucLQG6e1coAv^cbgwQEOp =bdWM_{6Fgr#KWW1hwg-WL#fQK!#k(XUZzNQ6$A2RC(aY9 zvJR}2Yb;TJdA#C~f4RAT={jVD6wiNBei4T*k{+3Bv9gR7P5;b%D)c}QL(BE{a+w9; zME9$VYiFyD%0gP`?^pY1i;=dEbId9s3A&C5`9YZ`+xxb_w`y0o4GEa;{5&k&R$Tp= z5w$lWG$Qe(N)(*T+S@59D_bNb%?6X1Q(VF*k@_?vp|mDk+|w<-wmFQ1JjOMSlDy@$ zs{~bkBQ-@eZp5&@-w)$EI`s&Qe%>`bt2!Qz>Hf5!*c%b|0ly{`_2whl@V6Z 076yu;eUH=cp^A|Vf 9j!?;`O?gF5zG2^`{l#= ^DIHCvFcG4{JsJOQ>%B>sZbr3~N>!Pi t7&{U{}9@yyM-|+kv1_12{+ONTkIPZOVC}OS~crmlbNsCl{y3-Z$l&Zbl z!|!)6qwDvUHc|`t*9^!$&txM4iBUd2Fz!Cl%~j40ICbIC2Pj|mA5yI>e$#xxGcVoi z52CinyQC!JTh~CR*V$qG;c-At_Q3}N{h|K4Ws8&$@~J$^%jZ4=Ko+hvP&i+VJr_)* z2G2!F-H^8wJ@yO9O-7v*!A&n=jQboXdOExuuTaOh?1R!p@g&M-)U8nJmEbv(giH)= z5^v2%aECl Nq zreo91 z*PKV+9_u=5O_j2K*KC+Bi;A5oA;(D#)|ykm$7c;iBPZ_bVG2g*Dnvn_#9maLd<{7H zezJh}7a|04$k8V(M64XRMRgd*bwEsXj|4F4p$K}28-bQxLh7;o41dgkw!CB#=x}Z; zEv(G*-89G>_JR@z)L5*5X|a`v5G#BO6#G!bi*lzSu6Jwri3ngnF-zxQC*Y#y1Tg-3 zF<^m6dw1|t84= 6l;JwMnIxHe}|$J@-g-u!@GfznwICL;@ruJVeX|mes~+Xn#EK04odGq~A1Y zNkn(C_8`+W?$D?<{;R+?{_IbI?cci2x^^ic#iIk_Ys?-uS-X64s0C)D32Mz;1ExN^ zYq18%I?z}8cewxm2KP_8z}#b8Q(ymHb*@Ma0=mg?#TQ9VBP5(~e^#9}%~Xf1>UA|# zsYv_&tUBM=-p_w2!e&WOc=%Z$SoN8cxEX@NBZySL??Q>dL`8cjlRtVu?W!A-oN`kc z;biRsPfE?pR}x3~+qh8W7E~6bm)KHM!>gLARWjY{3E}=|WSfUe Pg(J0RdhBcdu>a4VdLHQz7qI-a$?`XPi~Tol+ClV z`A@;5$c1cEqGY-x>7tz1#HaKboy42D{gK5&V)pJ-+%ih_tX?aFyH W}_4+BEk}0vyBEl|f7!<)>7qLVs7B$I6M$MDfixJN- z=N6?MPg|x{tUy@3xLF`!O(tK1wn~s@jSP 9#Bnbm~_!MGdjmOpenUt66@D2s^Ro23A3t4!@!I^WNyz0Wu=Q zB<-KP{N-9|L Rg+ zY8oujr6 (Ep3r0^9!eH)RT;St(bn#> zuZwxtdR6}7eg=`f3Hc~7&3Npa{4&- v>>n&{Dc{fF6E07Em((Yr@5 z0Ga}VyrK4%kx TEKv9)g??R36L^S@^*DIr+bRTs`d`e3FDa~x*UBiF*MlUV4@dGblubmPCaFyE> zV8uEviz49Xl#UBE=Q~{|JLkJNQt^wueuk$P`@{UT7YF0gyB9wu)x>`tzTa{oxCRK6 z{~^h&7-(wjZcg9kVD#(Y^}5}&U{Lg>jvRblD;97n3f}wu{l_Dv7azdel&|+lB6628 z-(Cr=#CiXE8GIRc+#yL@_vG_u!`(SG;)4hAV2UDRaAh4z^_C7??A;aO$~~nDs4gkD z$Sl+Y+e4O-7b@1Dw_^}N#Hjox%vzlj=P3|MWLzC$2U+}nT|jAT3QH`bKi9}gOH6FI z=XFJ2i8i0Kzk*i+rY1r|>5ErgaF!rGJG1PmfP`cr9^VUe_u<%#m?h#HL=Y(kSmDCF zZ(o_;#aM !|0FnO z<%*uJ27|3cV(U4NfSMpi=W$(p(SP;D>SBsT>@>!V=MGZZ##g;z V!mE@BFTapb z2l4x^TDH%^;^MUe5Y{@jROHz7jH`)BchP^+mR#a59X#@jD&tCW%*v}8{KUbvb!1e* zja}wQDxa8FeUHWAQBEHA{o@G%txw!L-n^F+rx^C`{V;#6`O_RVq2TL38}@m1lc#xd zad~U21m9D?e?UTY*h4mUvhtl{#Nn`(h0FU0Pgi8?WcG@*g8sUrz@)ZnWdGy!G3!D0 z!I+<{2R}~hQ*S3M5)_!MXNgv?lR2be0nm3vK_2ldlT{ 9p%E891NAwv=E4w#&|>nPDk#li zQRA4 qzmgkQ3$|dB&OPfl7q`)K5nDmBBln*L@s+?v=`dq@mPGK+?ut};bwPi*@JO4>d7|DbIp2iz(*^9a}oO( zjV6Cv{%zYmv-Q~8G{z2bnQg_e#x$AAFnp``8P%tmna`q^_d>62zMFZi!e+4hYpQB0 z7eWLYj`io)w#&PuJ}J+`lM{=b4hM^H_+UJ#-KWf9w6 zwdsucD zRbm>5gkO0$%v($o!A*9h1hpI?cI>qb5tQ3!qmVte=Y}bXVN{}T qVBYK zTP4Y9w-d!m4My0o>VL)YM&6Cuvq|ns^5vr-BagI|q^NO#ynNd0otqV=i(AgTz9egr zEwJqynu#vCZI>??5-A{Pg>kdbrZz+ohEs$z1=YqLSZx#!)0OuE1!#5O6%A4BQI;R2 zYetnhmW5Za0qsG6QjruyB`4JUnWK1Zg@mJdCpGnAi9^}w!#Y2O3bmRHw6S{a6V(VO zw(;I#r%UEQvC1tW4b3z4W~_`qDe>eQ6|N~1ttBi-#8FoxGT5y(TALYhE>?LEM=f4g zmGrqEc-mWp6Iw68i_;v68MwlT7~YGaDRNz10aT@~d(@jX4Z8wlc9ZoYOsO;bLu7NE zBg5mYSl8~1HZ6DrR^Oy|AdDQ*5JdcP{9xk#z40G!QKX`WldArNy?J7Qxg;Ba&@O)S zfNd{j%p0(00MzXiz`b##HOE2kzV7sdLY=DmNBMZL&EZzLXuzB_Euaw!smiwa=#fkC zMfKmI37y89)5pbTcFO2aO&DXJH_DVbBr_<|i(3n~a hi@&xa#5sR=e&eqC#k@c&+RiY48Ss2> z|K?QS $1I;?n3&*<2Z0o>kR h*jYR(osau_j@dqsFmX;|#2ic!rk03>k zqo7nDZo)r`+Y23