diff --git a/web b/web deleted file mode 160000 index d0a99dc..0000000 --- a/web +++ /dev/null @@ -1 +0,0 @@ -Subproject commit d0a99dcf123cefe5aed5b263ccde7acd4949da2a diff --git a/web/.editorconfig b/web/.editorconfig new file mode 100644 index 0000000..68cc827 --- /dev/null +++ b/web/.editorconfig @@ -0,0 +1,9 @@ +root = true + +[*] +charset = utf-8 +indent_style = space +indent_size = 2 +end_of_line = unset +insert_final_newline = true +trim_trailing_whitespace = true diff --git a/web/.env.development b/web/.env.development new file mode 100644 index 0000000..318c4cb --- /dev/null +++ b/web/.env.development @@ -0,0 +1,12 @@ +# 是否使用Hash路由 +VITE_USE_HASH = 'true' + +# 资源公共路径,需要以 /开头和结尾 +VITE_PUBLIC_PATH = '/' + +# Axios 基础路径 +# VITE_AXIOS_BASE_URL = '/api' # 用于代理 +VITE_AXIOS_BASE_URL = 'https://mock.apipark.cn/m1/3776410-0-default' # apifox云端mock + +# 代理配置-target +VITE_PROXY_TARGET = 'http://localhost:8085' diff --git a/web/.env.production b/web/.env.production new file mode 100644 index 0000000..1b309e4 --- /dev/null +++ b/web/.env.production @@ -0,0 +1,10 @@ +# 是否使用Hash路由 +VITE_USE_HASH = 'false' + +# 资源公共路径,需要以 /开头和结尾 +VITE_PUBLIC_PATH = '/' + +VITE_AXIOS_BASE_URL = '/api' # 用于代理 + +# 代理配置-target +VITE_PROXY_TARGET = 'http://localhost:8085' diff --git a/web/.eslint-global-variables.json b/web/.eslint-global-variables.json new file mode 100644 index 0000000..4f9c397 --- /dev/null +++ b/web/.eslint-global-variables.json @@ -0,0 +1,63 @@ +{ + "globals": { + "$loadingBar": true, + "$message": true, + "$dialog": true, + "$notification": true, + "$modal": true, + "defineOptions": true, + "EffectScope": true, + "computed": true, + "createApp": true, + "customRef": true, + "defineAsyncComponent": true, + "defineComponent": true, + "effectScope": true, + "getCurrentInstance": true, + "getCurrentScope": true, + "h": true, + "inject": true, + "isProxy": true, + "isReactive": true, + "isReadonly": true, + "isRef": true, + "markRaw": true, + "nextTick": true, + "onActivated": true, + "onBeforeMount": true, + "onBeforeUnmount": true, + "onBeforeUpdate": true, + "onDeactivated": true, + "onErrorCaptured": true, + "onMounted": true, + "onRenderTracked": true, + "onRenderTriggered": true, + "onScopeDispose": true, + "onServerPrefetch": true, + "onUnmounted": true, + "onUpdated": true, + "provide": true, + "reactive": true, + "readonly": true, + "ref": true, + "resolveComponent": true, + "shallowReactive": true, + "shallowReadonly": true, + "shallowRef": true, + "toRaw": true, + "toRef": true, + "toRefs": true, + "triggerRef": true, + "unref": true, + "useAttrs": true, + "useCssModule": true, + "useCssVars": true, + "useRoute": true, + "useRouter": true, + "useSlots": true, + "watch": true, + "watchEffect": true, + "watchPostEffect": true, + "watchSyncEffect": true + } +} diff --git a/web/.npmrc b/web/.npmrc new file mode 100644 index 0000000..5cee373 --- /dev/null +++ b/web/.npmrc @@ -0,0 +1,3 @@ +registry=https://registry.npmmirror.com +shamefully-hoist=true +strict-peer-dependencies=false diff --git a/web/LICENSE b/web/LICENSE new file mode 100644 index 0000000..888e80f --- /dev/null +++ b/web/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 Ronnie Zhang(大脸怪) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/web/README.md b/web/README.md new file mode 100644 index 0000000..53c2ff5 --- /dev/null +++ b/web/README.md @@ -0,0 +1,89 @@ +

+ + Vue Naive Admin Logo + +

+

+ MIT License +

+ +## 简介 + +Vue Naive Admin 是一款极简风格的后台管理模板,包含前后端解决方案,前端使用 Vite + Vue3 + Pinia + Unocss,后端使用 Nestjs + TypeOrm + MySql,简单易用,赏心悦目,历经十几次重构和细节打磨,诚意满满!! + +## 设计理念 + +Vue Naive Admin 2022年2月开始开源,从 1.0 到现在的 2.0,一直秉持着`简单即正义`的理念,旨在帮助中小企业、在校大学生及个人开发者快速上手开发后台管理项目,为了降低使用者的学习成本,没有使用看似主流的 TypeScript(前端),这也使得 Vue Naive Admin 成为了市面上少有的 `使用 JavaScript 的 Vue3 后台管理模板`,而且还算优秀,得到了大量朋友的认可和喜爱。 + +## 特性 + +- 🆒 使用 **Vue3** 主流最新技术栈: `Vite + Vue3 + Pinia` +- 🍇 使用 **原子CSS**框架: `Unocss`,优雅、轻量、易用 +- 🍍 集成 `Pinia` 状态管理,支持状态持久化 +- 🤹 使用主流的 `iconify + unocss` 图标方案,支持自定义图标,支持动态渲染 +- 🎨 使用 Naive UI,`极致简洁的代码风格和清爽的页面设计`,审美在线,主题轻松定制 +- 👏 先进且易于理解的文件结构设计,多个模块之间**零耦合**,单个业务模块删除不影响其他模块 +- 🚀 `扁平化路由`设计,每一个组件都可以是一个页面,告别多级路由 `KeepAlive` 难实现问题 +- 🍒 `基于权限动态生成路由`,无需额外定义路由,`403和404页面可区分`,而不是无权限也跳404 +- 🔐 基于Redis集成 `无感刷新`,用户登录态可控,安全与体验缺一不可 +- ✨ 基于 Naive UI 封装 `message` 全局工具方法,支持批量提醒,支持跨页面单例模式 +- ⚡️ 基于 Naive UI 封装常用的业务组件,包含`Page` 组件、`CRUD` 表格组件及 `Modal`组件等,简单易用,减少大量重复性工作 + +## 极致的性能 + +![](https://docs.isme.top/Public/Uploads/2023-11-18/6558568b2b476.png) +![](https://docs.isme.top/Public/Uploads/2023-11-18/655853caa9ce8.png) + +## 2.0 和 1.0 区别 + +- 2.0 是基于 1.0 风格从 0 到 1 重新设计的,所以 2.0 看似跟 1.0 很像,但其实代码机构差别还挺大的。 +- 1.0 只提供前端,后端使用 Mock 模拟的,而 2.0 是全栈版,提供真实的后端接口。 +- 2.0 虽然版本高于 1.0,但复杂度却远低于 1.0,虽然 1.0 也很简单。 +- 2.0 的灵活度远高于 1.0,只要你愿意,你可以为每个页面单独定制一个 layout + +[体验1.0 | template.isme.top](https://template.isme.top) + +[体验2.0 | admin.isme.top](https://admin.isme.top) + +## Nestjs 后端 + +Vue Naive Admin 提供一套后端代码,技术栈使用 Nestjs + TypeOrm + MySql,内置 JWT、RABC及模板所需的一些基础接口。 + +- 源码-github: [isme-nest-serve | github](https://github.com/zclzone/isme-nest-serve) +- 源码-gitee: [isme-nest-serve | gitee](https://gitee.com/isme-admin/isme-nest-serve) + +## 文档 + +- 项目文档: [docs | vue-naive-admin](https://docs.isme.top/web/#/624306705/188522224) +- 接口文档: [apidoc | isme-nest-serve](https://apifox.com/apidoc/shared-ff4a4d32-c0d1-4caf-b0ee-6abc130f734a) + +> 注:有个比较常见的问题,就是如何添加菜单和修改菜单,由于项目是由后端控制菜单资源的,所以需要对接后端后在资源管理功能对菜单进行增删改,然后在角色管理功能给对应角色进行授权。具体如何对接后端,请参考 [项目文档](https://docs.isme.top/web/#/624306705/188522224)。当然,可能有些菜单你不想通过权限控制,那么你可以在 `/src/settings.js` 文件添加 basePermissions,只需对齐菜单资源的结构即可,结构可以参照 [接口文档](https://apifox.com/apidoc/shared-ff4a4d32-c0d1-4caf-b0ee-6abc130f734a/api-134536978)。 + +## 使用这个模板开始你的项目 + +[使用这个模板创建Github仓库](https://github.com/zclzone/vue-naive-admin/generate). + +或者使用 `degit` 克隆此仓库,这样将没有任何历史提交记录: + +```cmd +npx degit zclzone/vue-naive-admin +``` + +## 版权说明 + +本项目使用 `MIT协议`,默认授权给任何人,被授权人可免费地无限制的使用、复制、修改、合并、发布、发行、再许可、售卖本软件拷贝、并有权向被供应人授予同等的权利,但必须满足以下条件: + +- 复制、修改和发行本项目代码需包含原作者的版权及许可信息,包括但不限于文件头注释、协议等 + +简单来说,作者只想保留版权,没有任何其他限制。 + +## 其他已对接本项目的后端项目 + +- [isme-java-serve](https://github.com/DHBin/isme-java-serve): 一个轻量级的Java后端服务,基于SpringBoot、MybatisPlus、SaToken、MapStruct等实现,已对接 Vue Naive Admin 2.0。 +- [naive-admin-go](https://github.com/ituserxxx/naive-admin-go): 一个 Go 后端服务,基于 gin、gorm、mysql、jwt和session,已对接 Vue Naive Admin 2.0。 + +## 入群交流 + +添加微信,拉你进群 + +![](https://static.isme.top/image/coder_wx.jpg) diff --git a/web/build/index.js b/web/build/index.js new file mode 100644 index 0000000..985ced8 --- /dev/null +++ b/web/build/index.js @@ -0,0 +1,39 @@ +/********************************** + * @Author: Ronnie Zhang + * @LastEditor: Ronnie Zhang + * @LastEditTime: 2023/12/04 22:48:02 + * @Email: zclzone@outlook.com + * Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top + **********************************/ + +import path from 'node:path' +import { globSync } from 'glob' +import dynamicIcons from '../src/assets/icons/dynamic-icons' + +/** + * @usage 生成icons, 用于 unocss safelist,以支持页面动态渲染自定义图标 + */ +export function getIcons() { + const feFiles = globSync('src/assets/icons/feather/*.svg', { nodir: true, strict: true }) + const meFiles = globSync('src/assets/icons/isme/*.svg', { nodir: true, strict: true }) + const feIcons = feFiles.map((filePath) => { + const fileName = path.basename(filePath) // 获取文件名,包括后缀 + const fileNameWithoutExt = path.parse(fileName).name // 获取去除后缀的文件名 + return `i-fe:${fileNameWithoutExt}` + }) + const meIcons = meFiles.map((filePath) => { + const fileName = path.basename(filePath) // 获取文件名,包括后缀 + const fileNameWithoutExt = path.parse(fileName).name // 获取去除后缀的文件名 + return `i-me:${fileNameWithoutExt}` + }) + + return [...dynamicIcons, ...feIcons, ...meIcons] +} + +/** + * @usage 生成.vue文件路径列表,用于添加菜单时可下拉选择对应的.vue文件路径,防止手动输入报错 + */ +export function getPagePathes() { + const files = globSync('src/views/**/*.vue') + return files.map(item => `/${path.normalize(item).replace(/\\/g, '/')}`) +} diff --git a/web/build/plugin-isme/icons.js b/web/build/plugin-isme/icons.js new file mode 100644 index 0000000..4da9779 --- /dev/null +++ b/web/build/plugin-isme/icons.js @@ -0,0 +1,25 @@ +/********************************** + * @Author: Ronnie Zhang + * @LastEditor: Ronnie Zhang + * @LastEditTime: 2023/12/04 22:48:11 + * @Email: zclzone@outlook.com + * Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top + **********************************/ + +import { getIcons } from '..' + +const PLUGIN_ICONS_ID = 'isme:icons' +export function pluginIcons() { + return { + name: 'isme:icons', + resolveId(id) { + if (id === PLUGIN_ICONS_ID) + return `\0${PLUGIN_ICONS_ID}` + }, + load(id) { + if (id === `\0${PLUGIN_ICONS_ID}`) { + return `export default ${JSON.stringify(getIcons())}` + } + }, + } +} diff --git a/web/build/plugin-isme/index.js b/web/build/plugin-isme/index.js new file mode 100644 index 0000000..326b960 --- /dev/null +++ b/web/build/plugin-isme/index.js @@ -0,0 +1,10 @@ +/********************************** + * @Author: Ronnie Zhang + * @LastEditor: Ronnie Zhang + * @LastEditTime: 2023/12/04 22:48:17 + * @Email: zclzone@outlook.com + * Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top + **********************************/ + +export { pluginPagePathes } from './page-pathes' +export { pluginIcons } from './icons' diff --git a/web/build/plugin-isme/page-pathes.js b/web/build/plugin-isme/page-pathes.js new file mode 100644 index 0000000..a29d8e2 --- /dev/null +++ b/web/build/plugin-isme/page-pathes.js @@ -0,0 +1,25 @@ +/********************************** + * @Author: Ronnie Zhang + * @LastEditor: Ronnie Zhang + * @LastEditTime: 2023/12/05 21:37:43 + * @Email: zclzone@outlook.com + * Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top + **********************************/ + +import { getPagePathes } from '..' + +const PLUGIN_PAGE_PATHES_ID = 'isme:page-pathes' +export function pluginPagePathes() { + return { + name: 'isme:page-pathes', + resolveId(id) { + if (id === PLUGIN_PAGE_PATHES_ID) + return `\0${PLUGIN_PAGE_PATHES_ID}` + }, + load(id) { + if (id === `\0${PLUGIN_PAGE_PATHES_ID}`) { + return `export default ${JSON.stringify(getPagePathes())}` + } + }, + } +} diff --git a/web/eslint.config.js b/web/eslint.config.js new file mode 100644 index 0000000..b15d4e5 --- /dev/null +++ b/web/eslint.config.js @@ -0,0 +1,34 @@ +import antfu from '@antfu/eslint-config' + +export default antfu({ + unocss: true, + formatters: true, + stylistic: true, + rules: { + 'n/prefer-global/process': 'off', + 'no-undef': 'error', + 'no-fallthrough': 'off', + 'vue/block-order': 'off', + '@typescript-eslint/no-this-alias': 'off', + 'prefer-promise-reject-errors': 'off', + }, + languageOptions: { + globals: { + h: 'readonly', + unref: 'readonly', + provide: 'readonly', + inject: 'readonly', + markRaw: 'readonly', + defineAsyncComponent: 'readonly', + nextTick: 'readonly', + useRoute: 'readonly', + useRouter: 'readonly', + Message: 'readonly', + $loadingBar: 'readonly', + $message: 'readonly', + $dialog: 'readonly', + $notification: 'readonly', + $modal: 'readonly', + }, + }, +}) diff --git a/web/index.html b/web/index.html new file mode 100644 index 0000000..ce02b2d --- /dev/null +++ b/web/index.html @@ -0,0 +1,94 @@ + + + + + + + %VITE_TITLE% + + + +
+
+
+ + + + + +
+
+
+ + + diff --git a/web/jsconfig.json b/web/jsconfig.json new file mode 100644 index 0000000..270b986 --- /dev/null +++ b/web/jsconfig.json @@ -0,0 +1,14 @@ +{ + "compilerOptions": { + "target": "ESNext", + "baseUrl": "./", + "moduleResolution": "node", + "paths": { + "@/*": ["src/*"], + "~/*": ["./*"] + }, + "jsx": "preserve", + "allowJs": true + }, + "exclude": ["node_modules", "dist"] +} diff --git a/web/package.json b/web/package.json new file mode 100644 index 0000000..fd9d2dc --- /dev/null +++ b/web/package.json @@ -0,0 +1,60 @@ +{ + "name": "vue-naive-admin", + "type": "module", + "version": "2.0.0", + "private": true, + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview", + "lint:fix": "eslint --fix", + "postinstall": "npx simple-git-hooks", + "up": "taze major -I" + }, + "dependencies": { + "@arco-design/color": "^0.4.0", + "@vueuse/core": "^10.11.0", + "axios": "^1.7.2", + "dayjs": "^1.11.11", + "echarts": "^5.5.1", + "lodash-es": "^4.17.21", + "naive-ui": "^2.38.2", + "pinia": "^2.1.7", + "pinia-plugin-persistedstate": "^3.2.1", + "vue": "^3.4.31", + "vue-echarts": "^6.7.3", + "vue-router": "^4.4.0", + "xlsx": "^0.18.5" + }, + "devDependencies": { + "@antfu/eslint-config": "^2.21.2", + "@iconify/json": "^2.2.223", + "@iconify/utils": "^2.1.25", + "@unocss/eslint-config": "^0.61.0", + "@unocss/eslint-plugin": "^0.61.0", + "@unocss/preset-rem-to-px": "^0.61.0", + "@vitejs/plugin-vue": "^5.0.5", + "eslint": "^9.6.0", + "eslint-plugin-format": "^0.1.2", + "esno": "^4.7.0", + "fs-extra": "^11.2.0", + "glob": "^10.4.2", + "lint-staged": "^15.2.7", + "rollup-plugin-visualizer": "^5.12.0", + "sass": "^1.77.6", + "simple-git-hooks": "^2.11.1", + "taze": "^0.13.9", + "unocss": "^0.61.0", + "unplugin-auto-import": "^0.17.6", + "unplugin-vue-components": "^0.27.2", + "vite": "^5.3.2", + "vite-plugin-router-warn": "^1.0.0", + "vite-plugin-vue-devtools": "^7.3.5" + }, + "simple-git-hooks": { + "pre-commit": "pnpm lint-staged" + }, + "lint-staged": { + "*": "eslint --fix" + } +} diff --git a/web/public/favicon.png b/web/public/favicon.png new file mode 100644 index 0000000..929c58a Binary files /dev/null and b/web/public/favicon.png differ diff --git a/web/src/App.vue b/web/src/App.vue new file mode 100644 index 0000000..ccad917 --- /dev/null +++ b/web/src/App.vue @@ -0,0 +1,63 @@ + + + + + diff --git a/web/src/api/index.js b/web/src/api/index.js new file mode 100644 index 0000000..23cbe93 --- /dev/null +++ b/web/src/api/index.js @@ -0,0 +1,24 @@ +/********************************** + * @Author: Ronnie Zhang + * @LastEditor: Ronnie Zhang + * @LastEditTime: 2023/12/04 22:50:38 + * @Email: zclzone@outlook.com + * Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top + **********************************/ + +import { request } from '@/utils' + +export default { + // 获取用户信息 + getUser: () => request.get('/user/detail'), + // 刷新token + refreshToken: () => request.get('/auth/refresh/token'), + // 登出 + logout: () => request.post('/auth/logout', {}, { needTip: false }), + // 切换当前角色 + switchCurrentRole: role => request.post(`/auth/current-role/switch/${role}`), + // 获取角色权限 + getRolePermissions: () => request.get('/role/permissions/tree'), + // 验证菜单路径 + validateMenuPath: path => request.get(`/permission/menu/validate?path=${path}`), +} diff --git a/web/src/assets/icons/dynamic-icons.js b/web/src/assets/icons/dynamic-icons.js new file mode 100644 index 0000000..5326f66 --- /dev/null +++ b/web/src/assets/icons/dynamic-icons.js @@ -0,0 +1,10 @@ +/********************************** + * @Author: Ronnie Zhang + * @LastEditor: Ronnie Zhang + * @LastEditTime: 2023/12/04 22:50:49 + * @Email: zclzone@outlook.com + * Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top + **********************************/ + +// 需要动态渲染的iconify图标,以i-开头 +export default ['i-simple-icons:juejin'] diff --git a/web/src/assets/icons/feather/activity.svg b/web/src/assets/icons/feather/activity.svg new file mode 100644 index 0000000..669a57a --- /dev/null +++ b/web/src/assets/icons/feather/activity.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/airplay.svg b/web/src/assets/icons/feather/airplay.svg new file mode 100644 index 0000000..7ce7302 --- /dev/null +++ b/web/src/assets/icons/feather/airplay.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/alert-circle.svg b/web/src/assets/icons/feather/alert-circle.svg new file mode 100644 index 0000000..8d02b7d --- /dev/null +++ b/web/src/assets/icons/feather/alert-circle.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/alert-octagon.svg b/web/src/assets/icons/feather/alert-octagon.svg new file mode 100644 index 0000000..de9b03f --- /dev/null +++ b/web/src/assets/icons/feather/alert-octagon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/alert-triangle.svg b/web/src/assets/icons/feather/alert-triangle.svg new file mode 100644 index 0000000..6dcb096 --- /dev/null +++ b/web/src/assets/icons/feather/alert-triangle.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/align-center.svg b/web/src/assets/icons/feather/align-center.svg new file mode 100644 index 0000000..5b8842e --- /dev/null +++ b/web/src/assets/icons/feather/align-center.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/align-justify.svg b/web/src/assets/icons/feather/align-justify.svg new file mode 100644 index 0000000..0539876 --- /dev/null +++ b/web/src/assets/icons/feather/align-justify.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/align-left.svg b/web/src/assets/icons/feather/align-left.svg new file mode 100644 index 0000000..9ac852a --- /dev/null +++ b/web/src/assets/icons/feather/align-left.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/align-right.svg b/web/src/assets/icons/feather/align-right.svg new file mode 100644 index 0000000..ef139ff --- /dev/null +++ b/web/src/assets/icons/feather/align-right.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/anchor.svg b/web/src/assets/icons/feather/anchor.svg new file mode 100644 index 0000000..e01627a --- /dev/null +++ b/web/src/assets/icons/feather/anchor.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/aperture.svg b/web/src/assets/icons/feather/aperture.svg new file mode 100644 index 0000000..9936e86 --- /dev/null +++ b/web/src/assets/icons/feather/aperture.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/archive.svg b/web/src/assets/icons/feather/archive.svg new file mode 100644 index 0000000..428882c --- /dev/null +++ b/web/src/assets/icons/feather/archive.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/arrow-down-circle.svg b/web/src/assets/icons/feather/arrow-down-circle.svg new file mode 100644 index 0000000..3238091 --- /dev/null +++ b/web/src/assets/icons/feather/arrow-down-circle.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/arrow-down-left.svg b/web/src/assets/icons/feather/arrow-down-left.svg new file mode 100644 index 0000000..7248358 --- /dev/null +++ b/web/src/assets/icons/feather/arrow-down-left.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/arrow-down-right.svg b/web/src/assets/icons/feather/arrow-down-right.svg new file mode 100644 index 0000000..81d9822 --- /dev/null +++ b/web/src/assets/icons/feather/arrow-down-right.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/arrow-down.svg b/web/src/assets/icons/feather/arrow-down.svg new file mode 100644 index 0000000..4f84f62 --- /dev/null +++ b/web/src/assets/icons/feather/arrow-down.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/arrow-left-circle.svg b/web/src/assets/icons/feather/arrow-left-circle.svg new file mode 100644 index 0000000..3b19ff8 --- /dev/null +++ b/web/src/assets/icons/feather/arrow-left-circle.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/arrow-left.svg b/web/src/assets/icons/feather/arrow-left.svg new file mode 100644 index 0000000..a5058fc --- /dev/null +++ b/web/src/assets/icons/feather/arrow-left.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/arrow-right-circle.svg b/web/src/assets/icons/feather/arrow-right-circle.svg new file mode 100644 index 0000000..ff01dd5 --- /dev/null +++ b/web/src/assets/icons/feather/arrow-right-circle.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/arrow-right.svg b/web/src/assets/icons/feather/arrow-right.svg new file mode 100644 index 0000000..939b57c --- /dev/null +++ b/web/src/assets/icons/feather/arrow-right.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/arrow-up-circle.svg b/web/src/assets/icons/feather/arrow-up-circle.svg new file mode 100644 index 0000000..044a75d --- /dev/null +++ b/web/src/assets/icons/feather/arrow-up-circle.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/arrow-up-left.svg b/web/src/assets/icons/feather/arrow-up-left.svg new file mode 100644 index 0000000..cea55e8 --- /dev/null +++ b/web/src/assets/icons/feather/arrow-up-left.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/arrow-up-right.svg b/web/src/assets/icons/feather/arrow-up-right.svg new file mode 100644 index 0000000..95678e0 --- /dev/null +++ b/web/src/assets/icons/feather/arrow-up-right.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/arrow-up.svg b/web/src/assets/icons/feather/arrow-up.svg new file mode 100644 index 0000000..16b13ab --- /dev/null +++ b/web/src/assets/icons/feather/arrow-up.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/at-sign.svg b/web/src/assets/icons/feather/at-sign.svg new file mode 100644 index 0000000..5a5e5d0 --- /dev/null +++ b/web/src/assets/icons/feather/at-sign.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/award.svg b/web/src/assets/icons/feather/award.svg new file mode 100644 index 0000000..be70d5a --- /dev/null +++ b/web/src/assets/icons/feather/award.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/bar-chart-2.svg b/web/src/assets/icons/feather/bar-chart-2.svg new file mode 100644 index 0000000..864167a --- /dev/null +++ b/web/src/assets/icons/feather/bar-chart-2.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/bar-chart.svg b/web/src/assets/icons/feather/bar-chart.svg new file mode 100644 index 0000000..074d7c1 --- /dev/null +++ b/web/src/assets/icons/feather/bar-chart.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/battery-charging.svg b/web/src/assets/icons/feather/battery-charging.svg new file mode 100644 index 0000000..644cb59 --- /dev/null +++ b/web/src/assets/icons/feather/battery-charging.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/battery.svg b/web/src/assets/icons/feather/battery.svg new file mode 100644 index 0000000..7fe8771 --- /dev/null +++ b/web/src/assets/icons/feather/battery.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/bell-off.svg b/web/src/assets/icons/feather/bell-off.svg new file mode 100644 index 0000000..4b07c84 --- /dev/null +++ b/web/src/assets/icons/feather/bell-off.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/bell.svg b/web/src/assets/icons/feather/bell.svg new file mode 100644 index 0000000..bba561c --- /dev/null +++ b/web/src/assets/icons/feather/bell.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/bluetooth.svg b/web/src/assets/icons/feather/bluetooth.svg new file mode 100644 index 0000000..cebed7b --- /dev/null +++ b/web/src/assets/icons/feather/bluetooth.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/bold.svg b/web/src/assets/icons/feather/bold.svg new file mode 100644 index 0000000..d1a4efd --- /dev/null +++ b/web/src/assets/icons/feather/bold.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/book-open.svg b/web/src/assets/icons/feather/book-open.svg new file mode 100644 index 0000000..5e0ca0a --- /dev/null +++ b/web/src/assets/icons/feather/book-open.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/book.svg b/web/src/assets/icons/feather/book.svg new file mode 100644 index 0000000..12ffcbc --- /dev/null +++ b/web/src/assets/icons/feather/book.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/bookmark.svg b/web/src/assets/icons/feather/bookmark.svg new file mode 100644 index 0000000..2239cc5 --- /dev/null +++ b/web/src/assets/icons/feather/bookmark.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/box.svg b/web/src/assets/icons/feather/box.svg new file mode 100644 index 0000000..d89be30 --- /dev/null +++ b/web/src/assets/icons/feather/box.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/briefcase.svg b/web/src/assets/icons/feather/briefcase.svg new file mode 100644 index 0000000..e3af050 --- /dev/null +++ b/web/src/assets/icons/feather/briefcase.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/calendar.svg b/web/src/assets/icons/feather/calendar.svg new file mode 100644 index 0000000..6c7fd87 --- /dev/null +++ b/web/src/assets/icons/feather/calendar.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/camera-off.svg b/web/src/assets/icons/feather/camera-off.svg new file mode 100644 index 0000000..daa3e25 --- /dev/null +++ b/web/src/assets/icons/feather/camera-off.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/camera.svg b/web/src/assets/icons/feather/camera.svg new file mode 100644 index 0000000..0e7f060 --- /dev/null +++ b/web/src/assets/icons/feather/camera.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/cast.svg b/web/src/assets/icons/feather/cast.svg new file mode 100644 index 0000000..63c954d --- /dev/null +++ b/web/src/assets/icons/feather/cast.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/check-circle.svg b/web/src/assets/icons/feather/check-circle.svg new file mode 100644 index 0000000..f2f4fd1 --- /dev/null +++ b/web/src/assets/icons/feather/check-circle.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/check-square.svg b/web/src/assets/icons/feather/check-square.svg new file mode 100644 index 0000000..72ab7a8 --- /dev/null +++ b/web/src/assets/icons/feather/check-square.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/check.svg b/web/src/assets/icons/feather/check.svg new file mode 100644 index 0000000..1c20989 --- /dev/null +++ b/web/src/assets/icons/feather/check.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/chevron-down.svg b/web/src/assets/icons/feather/chevron-down.svg new file mode 100644 index 0000000..278c6a3 --- /dev/null +++ b/web/src/assets/icons/feather/chevron-down.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/chevron-left.svg b/web/src/assets/icons/feather/chevron-left.svg new file mode 100644 index 0000000..747d46d --- /dev/null +++ b/web/src/assets/icons/feather/chevron-left.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/chevron-right.svg b/web/src/assets/icons/feather/chevron-right.svg new file mode 100644 index 0000000..258de41 --- /dev/null +++ b/web/src/assets/icons/feather/chevron-right.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/chevron-up.svg b/web/src/assets/icons/feather/chevron-up.svg new file mode 100644 index 0000000..4eb5ecc --- /dev/null +++ b/web/src/assets/icons/feather/chevron-up.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/chevrons-down.svg b/web/src/assets/icons/feather/chevrons-down.svg new file mode 100644 index 0000000..e67ef2f --- /dev/null +++ b/web/src/assets/icons/feather/chevrons-down.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/chevrons-left.svg b/web/src/assets/icons/feather/chevrons-left.svg new file mode 100644 index 0000000..c32e398 --- /dev/null +++ b/web/src/assets/icons/feather/chevrons-left.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/chevrons-right.svg b/web/src/assets/icons/feather/chevrons-right.svg new file mode 100644 index 0000000..f506814 --- /dev/null +++ b/web/src/assets/icons/feather/chevrons-right.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/chevrons-up.svg b/web/src/assets/icons/feather/chevrons-up.svg new file mode 100644 index 0000000..0eaf518 --- /dev/null +++ b/web/src/assets/icons/feather/chevrons-up.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/chrome.svg b/web/src/assets/icons/feather/chrome.svg new file mode 100644 index 0000000..9189815 --- /dev/null +++ b/web/src/assets/icons/feather/chrome.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/circle.svg b/web/src/assets/icons/feather/circle.svg new file mode 100644 index 0000000..b009088 --- /dev/null +++ b/web/src/assets/icons/feather/circle.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/clipboard.svg b/web/src/assets/icons/feather/clipboard.svg new file mode 100644 index 0000000..ccee454 --- /dev/null +++ b/web/src/assets/icons/feather/clipboard.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/clock.svg b/web/src/assets/icons/feather/clock.svg new file mode 100644 index 0000000..ea3f5e5 --- /dev/null +++ b/web/src/assets/icons/feather/clock.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/cloud-drizzle.svg b/web/src/assets/icons/feather/cloud-drizzle.svg new file mode 100644 index 0000000..13af6bb --- /dev/null +++ b/web/src/assets/icons/feather/cloud-drizzle.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/cloud-lightning.svg b/web/src/assets/icons/feather/cloud-lightning.svg new file mode 100644 index 0000000..32d154c --- /dev/null +++ b/web/src/assets/icons/feather/cloud-lightning.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/cloud-off.svg b/web/src/assets/icons/feather/cloud-off.svg new file mode 100644 index 0000000..1e1e7d6 --- /dev/null +++ b/web/src/assets/icons/feather/cloud-off.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/cloud-rain.svg b/web/src/assets/icons/feather/cloud-rain.svg new file mode 100644 index 0000000..3e0b85b --- /dev/null +++ b/web/src/assets/icons/feather/cloud-rain.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/cloud-snow.svg b/web/src/assets/icons/feather/cloud-snow.svg new file mode 100644 index 0000000..e4eb820 --- /dev/null +++ b/web/src/assets/icons/feather/cloud-snow.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/cloud.svg b/web/src/assets/icons/feather/cloud.svg new file mode 100644 index 0000000..0ee0c63 --- /dev/null +++ b/web/src/assets/icons/feather/cloud.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/code.svg b/web/src/assets/icons/feather/code.svg new file mode 100644 index 0000000..c4954b5 --- /dev/null +++ b/web/src/assets/icons/feather/code.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/codepen.svg b/web/src/assets/icons/feather/codepen.svg new file mode 100644 index 0000000..ab2a815 --- /dev/null +++ b/web/src/assets/icons/feather/codepen.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/codesandbox.svg b/web/src/assets/icons/feather/codesandbox.svg new file mode 100644 index 0000000..49848f5 --- /dev/null +++ b/web/src/assets/icons/feather/codesandbox.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/coffee.svg b/web/src/assets/icons/feather/coffee.svg new file mode 100644 index 0000000..32905e5 --- /dev/null +++ b/web/src/assets/icons/feather/coffee.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/columns.svg b/web/src/assets/icons/feather/columns.svg new file mode 100644 index 0000000..d264b55 --- /dev/null +++ b/web/src/assets/icons/feather/columns.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/command.svg b/web/src/assets/icons/feather/command.svg new file mode 100644 index 0000000..93f554c --- /dev/null +++ b/web/src/assets/icons/feather/command.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/compass.svg b/web/src/assets/icons/feather/compass.svg new file mode 100644 index 0000000..3296260 --- /dev/null +++ b/web/src/assets/icons/feather/compass.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/copy.svg b/web/src/assets/icons/feather/copy.svg new file mode 100644 index 0000000..4e0b09f --- /dev/null +++ b/web/src/assets/icons/feather/copy.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/corner-down-left.svg b/web/src/assets/icons/feather/corner-down-left.svg new file mode 100644 index 0000000..9fffb3e --- /dev/null +++ b/web/src/assets/icons/feather/corner-down-left.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/corner-down-right.svg b/web/src/assets/icons/feather/corner-down-right.svg new file mode 100644 index 0000000..b27d408 --- /dev/null +++ b/web/src/assets/icons/feather/corner-down-right.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/corner-left-down.svg b/web/src/assets/icons/feather/corner-left-down.svg new file mode 100644 index 0000000..24b8375 --- /dev/null +++ b/web/src/assets/icons/feather/corner-left-down.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/corner-left-up.svg b/web/src/assets/icons/feather/corner-left-up.svg new file mode 100644 index 0000000..e54527c --- /dev/null +++ b/web/src/assets/icons/feather/corner-left-up.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/corner-right-down.svg b/web/src/assets/icons/feather/corner-right-down.svg new file mode 100644 index 0000000..a49e6d6 --- /dev/null +++ b/web/src/assets/icons/feather/corner-right-down.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/corner-right-up.svg b/web/src/assets/icons/feather/corner-right-up.svg new file mode 100644 index 0000000..a5c5dce --- /dev/null +++ b/web/src/assets/icons/feather/corner-right-up.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/corner-up-left.svg b/web/src/assets/icons/feather/corner-up-left.svg new file mode 100644 index 0000000..0a1ffd6 --- /dev/null +++ b/web/src/assets/icons/feather/corner-up-left.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/corner-up-right.svg b/web/src/assets/icons/feather/corner-up-right.svg new file mode 100644 index 0000000..0b8f961 --- /dev/null +++ b/web/src/assets/icons/feather/corner-up-right.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/cpu.svg b/web/src/assets/icons/feather/cpu.svg new file mode 100644 index 0000000..2ed16ef --- /dev/null +++ b/web/src/assets/icons/feather/cpu.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/credit-card.svg b/web/src/assets/icons/feather/credit-card.svg new file mode 100644 index 0000000..1b7fd02 --- /dev/null +++ b/web/src/assets/icons/feather/credit-card.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/crop.svg b/web/src/assets/icons/feather/crop.svg new file mode 100644 index 0000000..ffbfd04 --- /dev/null +++ b/web/src/assets/icons/feather/crop.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/crosshair.svg b/web/src/assets/icons/feather/crosshair.svg new file mode 100644 index 0000000..ba39401 --- /dev/null +++ b/web/src/assets/icons/feather/crosshair.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/database.svg b/web/src/assets/icons/feather/database.svg new file mode 100644 index 0000000..c296fbc --- /dev/null +++ b/web/src/assets/icons/feather/database.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/delete.svg b/web/src/assets/icons/feather/delete.svg new file mode 100644 index 0000000..8c6074b --- /dev/null +++ b/web/src/assets/icons/feather/delete.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/disc.svg b/web/src/assets/icons/feather/disc.svg new file mode 100644 index 0000000..2595b44 --- /dev/null +++ b/web/src/assets/icons/feather/disc.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/divide.svg b/web/src/assets/icons/feather/divide.svg new file mode 100644 index 0000000..3cbff3a --- /dev/null +++ b/web/src/assets/icons/feather/divide.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/dollar-sign.svg b/web/src/assets/icons/feather/dollar-sign.svg new file mode 100644 index 0000000..1a124d2 --- /dev/null +++ b/web/src/assets/icons/feather/dollar-sign.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/download-cloud.svg b/web/src/assets/icons/feather/download-cloud.svg new file mode 100644 index 0000000..f3126fc --- /dev/null +++ b/web/src/assets/icons/feather/download-cloud.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/download.svg b/web/src/assets/icons/feather/download.svg new file mode 100644 index 0000000..76767a9 --- /dev/null +++ b/web/src/assets/icons/feather/download.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/dribbble.svg b/web/src/assets/icons/feather/dribbble.svg new file mode 100644 index 0000000..bb8577d --- /dev/null +++ b/web/src/assets/icons/feather/dribbble.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/droplet.svg b/web/src/assets/icons/feather/droplet.svg new file mode 100644 index 0000000..ca09301 --- /dev/null +++ b/web/src/assets/icons/feather/droplet.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/edit-2.svg b/web/src/assets/icons/feather/edit-2.svg new file mode 100644 index 0000000..06830c9 --- /dev/null +++ b/web/src/assets/icons/feather/edit-2.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/edit-3.svg b/web/src/assets/icons/feather/edit-3.svg new file mode 100644 index 0000000..d728efc --- /dev/null +++ b/web/src/assets/icons/feather/edit-3.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/edit.svg b/web/src/assets/icons/feather/edit.svg new file mode 100644 index 0000000..ec7b4ca --- /dev/null +++ b/web/src/assets/icons/feather/edit.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/external-link.svg b/web/src/assets/icons/feather/external-link.svg new file mode 100644 index 0000000..6236df3 --- /dev/null +++ b/web/src/assets/icons/feather/external-link.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/eye-off.svg b/web/src/assets/icons/feather/eye-off.svg new file mode 100644 index 0000000..77c54cb --- /dev/null +++ b/web/src/assets/icons/feather/eye-off.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/eye.svg b/web/src/assets/icons/feather/eye.svg new file mode 100644 index 0000000..9cde243 --- /dev/null +++ b/web/src/assets/icons/feather/eye.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/facebook.svg b/web/src/assets/icons/feather/facebook.svg new file mode 100644 index 0000000..2570f56 --- /dev/null +++ b/web/src/assets/icons/feather/facebook.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/fast-forward.svg b/web/src/assets/icons/feather/fast-forward.svg new file mode 100644 index 0000000..fa39877 --- /dev/null +++ b/web/src/assets/icons/feather/fast-forward.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/feather.svg b/web/src/assets/icons/feather/feather.svg new file mode 100644 index 0000000..ac3b868 --- /dev/null +++ b/web/src/assets/icons/feather/feather.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/figma.svg b/web/src/assets/icons/feather/figma.svg new file mode 100644 index 0000000..66fd217 --- /dev/null +++ b/web/src/assets/icons/feather/figma.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/file-minus.svg b/web/src/assets/icons/feather/file-minus.svg new file mode 100644 index 0000000..345756e --- /dev/null +++ b/web/src/assets/icons/feather/file-minus.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/file-plus.svg b/web/src/assets/icons/feather/file-plus.svg new file mode 100644 index 0000000..eed1200 --- /dev/null +++ b/web/src/assets/icons/feather/file-plus.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/file-text.svg b/web/src/assets/icons/feather/file-text.svg new file mode 100644 index 0000000..4197ddd --- /dev/null +++ b/web/src/assets/icons/feather/file-text.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/file.svg b/web/src/assets/icons/feather/file.svg new file mode 100644 index 0000000..378519a --- /dev/null +++ b/web/src/assets/icons/feather/file.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/film.svg b/web/src/assets/icons/feather/film.svg new file mode 100644 index 0000000..ac46360 --- /dev/null +++ b/web/src/assets/icons/feather/film.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/filter.svg b/web/src/assets/icons/feather/filter.svg new file mode 100644 index 0000000..38a47e0 --- /dev/null +++ b/web/src/assets/icons/feather/filter.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/flag.svg b/web/src/assets/icons/feather/flag.svg new file mode 100644 index 0000000..037737c --- /dev/null +++ b/web/src/assets/icons/feather/flag.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/folder-minus.svg b/web/src/assets/icons/feather/folder-minus.svg new file mode 100644 index 0000000..d5b7af6 --- /dev/null +++ b/web/src/assets/icons/feather/folder-minus.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/folder-plus.svg b/web/src/assets/icons/feather/folder-plus.svg new file mode 100644 index 0000000..898f2fc --- /dev/null +++ b/web/src/assets/icons/feather/folder-plus.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/folder.svg b/web/src/assets/icons/feather/folder.svg new file mode 100644 index 0000000..134458b --- /dev/null +++ b/web/src/assets/icons/feather/folder.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/framer.svg b/web/src/assets/icons/feather/framer.svg new file mode 100644 index 0000000..3e66347 --- /dev/null +++ b/web/src/assets/icons/feather/framer.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/frown.svg b/web/src/assets/icons/feather/frown.svg new file mode 100644 index 0000000..f312254 --- /dev/null +++ b/web/src/assets/icons/feather/frown.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/gift.svg b/web/src/assets/icons/feather/gift.svg new file mode 100644 index 0000000..d2c14bd --- /dev/null +++ b/web/src/assets/icons/feather/gift.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/git-branch.svg b/web/src/assets/icons/feather/git-branch.svg new file mode 100644 index 0000000..4400372 --- /dev/null +++ b/web/src/assets/icons/feather/git-branch.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/git-commit.svg b/web/src/assets/icons/feather/git-commit.svg new file mode 100644 index 0000000..e959d72 --- /dev/null +++ b/web/src/assets/icons/feather/git-commit.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/git-merge.svg b/web/src/assets/icons/feather/git-merge.svg new file mode 100644 index 0000000..c65fffd --- /dev/null +++ b/web/src/assets/icons/feather/git-merge.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/git-pull-request.svg b/web/src/assets/icons/feather/git-pull-request.svg new file mode 100644 index 0000000..fc80bdf --- /dev/null +++ b/web/src/assets/icons/feather/git-pull-request.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/github.svg b/web/src/assets/icons/feather/github.svg new file mode 100644 index 0000000..ff0af48 --- /dev/null +++ b/web/src/assets/icons/feather/github.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/gitlab.svg b/web/src/assets/icons/feather/gitlab.svg new file mode 100644 index 0000000..85d54a1 --- /dev/null +++ b/web/src/assets/icons/feather/gitlab.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/globe.svg b/web/src/assets/icons/feather/globe.svg new file mode 100644 index 0000000..0a0586d --- /dev/null +++ b/web/src/assets/icons/feather/globe.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/grid.svg b/web/src/assets/icons/feather/grid.svg new file mode 100644 index 0000000..8ef2e9d --- /dev/null +++ b/web/src/assets/icons/feather/grid.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/hard-drive.svg b/web/src/assets/icons/feather/hard-drive.svg new file mode 100644 index 0000000..8e90fa1 --- /dev/null +++ b/web/src/assets/icons/feather/hard-drive.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/hash.svg b/web/src/assets/icons/feather/hash.svg new file mode 100644 index 0000000..c9c8d41 --- /dev/null +++ b/web/src/assets/icons/feather/hash.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/headphones.svg b/web/src/assets/icons/feather/headphones.svg new file mode 100644 index 0000000..fd8915b --- /dev/null +++ b/web/src/assets/icons/feather/headphones.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/heart.svg b/web/src/assets/icons/feather/heart.svg new file mode 100644 index 0000000..a083b7e --- /dev/null +++ b/web/src/assets/icons/feather/heart.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/help-circle.svg b/web/src/assets/icons/feather/help-circle.svg new file mode 100644 index 0000000..51fddd8 --- /dev/null +++ b/web/src/assets/icons/feather/help-circle.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/hexagon.svg b/web/src/assets/icons/feather/hexagon.svg new file mode 100644 index 0000000..eae7f25 --- /dev/null +++ b/web/src/assets/icons/feather/hexagon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/home.svg b/web/src/assets/icons/feather/home.svg new file mode 100644 index 0000000..7bb31b2 --- /dev/null +++ b/web/src/assets/icons/feather/home.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/image.svg b/web/src/assets/icons/feather/image.svg new file mode 100644 index 0000000..a7d84b9 --- /dev/null +++ b/web/src/assets/icons/feather/image.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/inbox.svg b/web/src/assets/icons/feather/inbox.svg new file mode 100644 index 0000000..03a13b4 --- /dev/null +++ b/web/src/assets/icons/feather/inbox.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/info.svg b/web/src/assets/icons/feather/info.svg new file mode 100644 index 0000000..a09fa5f --- /dev/null +++ b/web/src/assets/icons/feather/info.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/instagram.svg b/web/src/assets/icons/feather/instagram.svg new file mode 100644 index 0000000..9fdb8e3 --- /dev/null +++ b/web/src/assets/icons/feather/instagram.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/italic.svg b/web/src/assets/icons/feather/italic.svg new file mode 100644 index 0000000..a123d37 --- /dev/null +++ b/web/src/assets/icons/feather/italic.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/key.svg b/web/src/assets/icons/feather/key.svg new file mode 100644 index 0000000..e778e74 --- /dev/null +++ b/web/src/assets/icons/feather/key.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/layers.svg b/web/src/assets/icons/feather/layers.svg new file mode 100644 index 0000000..ea788c2 --- /dev/null +++ b/web/src/assets/icons/feather/layers.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/layout.svg b/web/src/assets/icons/feather/layout.svg new file mode 100644 index 0000000..28743d9 --- /dev/null +++ b/web/src/assets/icons/feather/layout.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/life-buoy.svg b/web/src/assets/icons/feather/life-buoy.svg new file mode 100644 index 0000000..54c2bd7 --- /dev/null +++ b/web/src/assets/icons/feather/life-buoy.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/link-2.svg b/web/src/assets/icons/feather/link-2.svg new file mode 100644 index 0000000..8cc7f6d --- /dev/null +++ b/web/src/assets/icons/feather/link-2.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/link.svg b/web/src/assets/icons/feather/link.svg new file mode 100644 index 0000000..c89dd41 --- /dev/null +++ b/web/src/assets/icons/feather/link.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/linkedin.svg b/web/src/assets/icons/feather/linkedin.svg new file mode 100644 index 0000000..3953109 --- /dev/null +++ b/web/src/assets/icons/feather/linkedin.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/list.svg b/web/src/assets/icons/feather/list.svg new file mode 100644 index 0000000..5ce38ea --- /dev/null +++ b/web/src/assets/icons/feather/list.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/loader.svg b/web/src/assets/icons/feather/loader.svg new file mode 100644 index 0000000..e1a70c1 --- /dev/null +++ b/web/src/assets/icons/feather/loader.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/lock.svg b/web/src/assets/icons/feather/lock.svg new file mode 100644 index 0000000..de09d9d --- /dev/null +++ b/web/src/assets/icons/feather/lock.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/log-in.svg b/web/src/assets/icons/feather/log-in.svg new file mode 100644 index 0000000..ba0da59 --- /dev/null +++ b/web/src/assets/icons/feather/log-in.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/log-out.svg b/web/src/assets/icons/feather/log-out.svg new file mode 100644 index 0000000..c9002c9 --- /dev/null +++ b/web/src/assets/icons/feather/log-out.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/mail.svg b/web/src/assets/icons/feather/mail.svg new file mode 100644 index 0000000..2af169e --- /dev/null +++ b/web/src/assets/icons/feather/mail.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/map-pin.svg b/web/src/assets/icons/feather/map-pin.svg new file mode 100644 index 0000000..d5548e9 --- /dev/null +++ b/web/src/assets/icons/feather/map-pin.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/map.svg b/web/src/assets/icons/feather/map.svg new file mode 100644 index 0000000..ecebd7b --- /dev/null +++ b/web/src/assets/icons/feather/map.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/maximize-2.svg b/web/src/assets/icons/feather/maximize-2.svg new file mode 100644 index 0000000..e41fc0b --- /dev/null +++ b/web/src/assets/icons/feather/maximize-2.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/maximize.svg b/web/src/assets/icons/feather/maximize.svg new file mode 100644 index 0000000..fc30518 --- /dev/null +++ b/web/src/assets/icons/feather/maximize.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/meh.svg b/web/src/assets/icons/feather/meh.svg new file mode 100644 index 0000000..6f57fff --- /dev/null +++ b/web/src/assets/icons/feather/meh.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/menu.svg b/web/src/assets/icons/feather/menu.svg new file mode 100644 index 0000000..e8a84a9 --- /dev/null +++ b/web/src/assets/icons/feather/menu.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/message-circle.svg b/web/src/assets/icons/feather/message-circle.svg new file mode 100644 index 0000000..4b21b32 --- /dev/null +++ b/web/src/assets/icons/feather/message-circle.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/message-square.svg b/web/src/assets/icons/feather/message-square.svg new file mode 100644 index 0000000..6a2e4e5 --- /dev/null +++ b/web/src/assets/icons/feather/message-square.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/mic-off.svg b/web/src/assets/icons/feather/mic-off.svg new file mode 100644 index 0000000..0786219 --- /dev/null +++ b/web/src/assets/icons/feather/mic-off.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/mic.svg b/web/src/assets/icons/feather/mic.svg new file mode 100644 index 0000000..dc5f780 --- /dev/null +++ b/web/src/assets/icons/feather/mic.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/minimize-2.svg b/web/src/assets/icons/feather/minimize-2.svg new file mode 100644 index 0000000..a720fa6 --- /dev/null +++ b/web/src/assets/icons/feather/minimize-2.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/minimize.svg b/web/src/assets/icons/feather/minimize.svg new file mode 100644 index 0000000..46d6119 --- /dev/null +++ b/web/src/assets/icons/feather/minimize.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/minus-circle.svg b/web/src/assets/icons/feather/minus-circle.svg new file mode 100644 index 0000000..80c0de1 --- /dev/null +++ b/web/src/assets/icons/feather/minus-circle.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/minus-square.svg b/web/src/assets/icons/feather/minus-square.svg new file mode 100644 index 0000000..4862832 --- /dev/null +++ b/web/src/assets/icons/feather/minus-square.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/minus.svg b/web/src/assets/icons/feather/minus.svg new file mode 100644 index 0000000..93cc734 --- /dev/null +++ b/web/src/assets/icons/feather/minus.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/monitor.svg b/web/src/assets/icons/feather/monitor.svg new file mode 100644 index 0000000..6c3556d --- /dev/null +++ b/web/src/assets/icons/feather/monitor.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/moon.svg b/web/src/assets/icons/feather/moon.svg new file mode 100644 index 0000000..dbf7c6c --- /dev/null +++ b/web/src/assets/icons/feather/moon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/more-horizontal.svg b/web/src/assets/icons/feather/more-horizontal.svg new file mode 100644 index 0000000..dc6a855 --- /dev/null +++ b/web/src/assets/icons/feather/more-horizontal.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/more-vertical.svg b/web/src/assets/icons/feather/more-vertical.svg new file mode 100644 index 0000000..cba6958 --- /dev/null +++ b/web/src/assets/icons/feather/more-vertical.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/mouse-pointer.svg b/web/src/assets/icons/feather/mouse-pointer.svg new file mode 100644 index 0000000..f5af559 --- /dev/null +++ b/web/src/assets/icons/feather/mouse-pointer.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/move.svg b/web/src/assets/icons/feather/move.svg new file mode 100644 index 0000000..4e251b5 --- /dev/null +++ b/web/src/assets/icons/feather/move.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/music.svg b/web/src/assets/icons/feather/music.svg new file mode 100644 index 0000000..7bee2f7 --- /dev/null +++ b/web/src/assets/icons/feather/music.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/navigation-2.svg b/web/src/assets/icons/feather/navigation-2.svg new file mode 100644 index 0000000..ae31db9 --- /dev/null +++ b/web/src/assets/icons/feather/navigation-2.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/navigation.svg b/web/src/assets/icons/feather/navigation.svg new file mode 100644 index 0000000..f600a41 --- /dev/null +++ b/web/src/assets/icons/feather/navigation.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/octagon.svg b/web/src/assets/icons/feather/octagon.svg new file mode 100644 index 0000000..124c548 --- /dev/null +++ b/web/src/assets/icons/feather/octagon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/package.svg b/web/src/assets/icons/feather/package.svg new file mode 100644 index 0000000..f1e09ee --- /dev/null +++ b/web/src/assets/icons/feather/package.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/paperclip.svg b/web/src/assets/icons/feather/paperclip.svg new file mode 100644 index 0000000..b1f69b7 --- /dev/null +++ b/web/src/assets/icons/feather/paperclip.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/pause-circle.svg b/web/src/assets/icons/feather/pause-circle.svg new file mode 100644 index 0000000..f6b1a8d --- /dev/null +++ b/web/src/assets/icons/feather/pause-circle.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/pause.svg b/web/src/assets/icons/feather/pause.svg new file mode 100644 index 0000000..4e78038 --- /dev/null +++ b/web/src/assets/icons/feather/pause.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/pen-tool.svg b/web/src/assets/icons/feather/pen-tool.svg new file mode 100644 index 0000000..0d26fa1 --- /dev/null +++ b/web/src/assets/icons/feather/pen-tool.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/percent.svg b/web/src/assets/icons/feather/percent.svg new file mode 100644 index 0000000..2cb9719 --- /dev/null +++ b/web/src/assets/icons/feather/percent.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/phone-call.svg b/web/src/assets/icons/feather/phone-call.svg new file mode 100644 index 0000000..8b86660 --- /dev/null +++ b/web/src/assets/icons/feather/phone-call.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/phone-forwarded.svg b/web/src/assets/icons/feather/phone-forwarded.svg new file mode 100644 index 0000000..aa21bef --- /dev/null +++ b/web/src/assets/icons/feather/phone-forwarded.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/phone-incoming.svg b/web/src/assets/icons/feather/phone-incoming.svg new file mode 100644 index 0000000..b2d523a --- /dev/null +++ b/web/src/assets/icons/feather/phone-incoming.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/phone-missed.svg b/web/src/assets/icons/feather/phone-missed.svg new file mode 100644 index 0000000..4950f09 --- /dev/null +++ b/web/src/assets/icons/feather/phone-missed.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/phone-off.svg b/web/src/assets/icons/feather/phone-off.svg new file mode 100644 index 0000000..4d00fb3 --- /dev/null +++ b/web/src/assets/icons/feather/phone-off.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/phone-outgoing.svg b/web/src/assets/icons/feather/phone-outgoing.svg new file mode 100644 index 0000000..fea27a3 --- /dev/null +++ b/web/src/assets/icons/feather/phone-outgoing.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/phone.svg b/web/src/assets/icons/feather/phone.svg new file mode 100644 index 0000000..2a35154 --- /dev/null +++ b/web/src/assets/icons/feather/phone.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/pie-chart.svg b/web/src/assets/icons/feather/pie-chart.svg new file mode 100644 index 0000000..b5bbe67 --- /dev/null +++ b/web/src/assets/icons/feather/pie-chart.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/play-circle.svg b/web/src/assets/icons/feather/play-circle.svg new file mode 100644 index 0000000..8766dc7 --- /dev/null +++ b/web/src/assets/icons/feather/play-circle.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/play.svg b/web/src/assets/icons/feather/play.svg new file mode 100644 index 0000000..fd76e30 --- /dev/null +++ b/web/src/assets/icons/feather/play.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/plus-circle.svg b/web/src/assets/icons/feather/plus-circle.svg new file mode 100644 index 0000000..4291ff0 --- /dev/null +++ b/web/src/assets/icons/feather/plus-circle.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/plus-square.svg b/web/src/assets/icons/feather/plus-square.svg new file mode 100644 index 0000000..c380e24 --- /dev/null +++ b/web/src/assets/icons/feather/plus-square.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/plus.svg b/web/src/assets/icons/feather/plus.svg new file mode 100644 index 0000000..703c5b7 --- /dev/null +++ b/web/src/assets/icons/feather/plus.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/pocket.svg b/web/src/assets/icons/feather/pocket.svg new file mode 100644 index 0000000..a3b2561 --- /dev/null +++ b/web/src/assets/icons/feather/pocket.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/power.svg b/web/src/assets/icons/feather/power.svg new file mode 100644 index 0000000..598308f --- /dev/null +++ b/web/src/assets/icons/feather/power.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/printer.svg b/web/src/assets/icons/feather/printer.svg new file mode 100644 index 0000000..8a9a7ac --- /dev/null +++ b/web/src/assets/icons/feather/printer.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/radio.svg b/web/src/assets/icons/feather/radio.svg new file mode 100644 index 0000000..5abfcd1 --- /dev/null +++ b/web/src/assets/icons/feather/radio.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/refresh-ccw.svg b/web/src/assets/icons/feather/refresh-ccw.svg new file mode 100644 index 0000000..10cff0e --- /dev/null +++ b/web/src/assets/icons/feather/refresh-ccw.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/refresh-cw.svg b/web/src/assets/icons/feather/refresh-cw.svg new file mode 100644 index 0000000..06c358d --- /dev/null +++ b/web/src/assets/icons/feather/refresh-cw.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/repeat.svg b/web/src/assets/icons/feather/repeat.svg new file mode 100644 index 0000000..c7657b0 --- /dev/null +++ b/web/src/assets/icons/feather/repeat.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/rewind.svg b/web/src/assets/icons/feather/rewind.svg new file mode 100644 index 0000000..7b0fa3d --- /dev/null +++ b/web/src/assets/icons/feather/rewind.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/rotate-ccw.svg b/web/src/assets/icons/feather/rotate-ccw.svg new file mode 100644 index 0000000..ade5dc4 --- /dev/null +++ b/web/src/assets/icons/feather/rotate-ccw.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/rotate-cw.svg b/web/src/assets/icons/feather/rotate-cw.svg new file mode 100644 index 0000000..83dca35 --- /dev/null +++ b/web/src/assets/icons/feather/rotate-cw.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/rss.svg b/web/src/assets/icons/feather/rss.svg new file mode 100644 index 0000000..c9a1368 --- /dev/null +++ b/web/src/assets/icons/feather/rss.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/save.svg b/web/src/assets/icons/feather/save.svg new file mode 100644 index 0000000..46c7299 --- /dev/null +++ b/web/src/assets/icons/feather/save.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/scissors.svg b/web/src/assets/icons/feather/scissors.svg new file mode 100644 index 0000000..fd0647f --- /dev/null +++ b/web/src/assets/icons/feather/scissors.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/search.svg b/web/src/assets/icons/feather/search.svg new file mode 100644 index 0000000..8710306 --- /dev/null +++ b/web/src/assets/icons/feather/search.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/send.svg b/web/src/assets/icons/feather/send.svg new file mode 100644 index 0000000..42ef2a2 --- /dev/null +++ b/web/src/assets/icons/feather/send.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/server.svg b/web/src/assets/icons/feather/server.svg new file mode 100644 index 0000000..54ce094 --- /dev/null +++ b/web/src/assets/icons/feather/server.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/settings.svg b/web/src/assets/icons/feather/settings.svg new file mode 100644 index 0000000..19c2726 --- /dev/null +++ b/web/src/assets/icons/feather/settings.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/share-2.svg b/web/src/assets/icons/feather/share-2.svg new file mode 100644 index 0000000..09b1c7b --- /dev/null +++ b/web/src/assets/icons/feather/share-2.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/share.svg b/web/src/assets/icons/feather/share.svg new file mode 100644 index 0000000..df38c14 --- /dev/null +++ b/web/src/assets/icons/feather/share.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/shield-off.svg b/web/src/assets/icons/feather/shield-off.svg new file mode 100644 index 0000000..18692dd --- /dev/null +++ b/web/src/assets/icons/feather/shield-off.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/shield.svg b/web/src/assets/icons/feather/shield.svg new file mode 100644 index 0000000..c7c4841 --- /dev/null +++ b/web/src/assets/icons/feather/shield.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/shopping-bag.svg b/web/src/assets/icons/feather/shopping-bag.svg new file mode 100644 index 0000000..eaa39e8 --- /dev/null +++ b/web/src/assets/icons/feather/shopping-bag.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/shopping-cart.svg b/web/src/assets/icons/feather/shopping-cart.svg new file mode 100644 index 0000000..17a40bf --- /dev/null +++ b/web/src/assets/icons/feather/shopping-cart.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/shuffle.svg b/web/src/assets/icons/feather/shuffle.svg new file mode 100644 index 0000000..8cfb5db --- /dev/null +++ b/web/src/assets/icons/feather/shuffle.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/sidebar.svg b/web/src/assets/icons/feather/sidebar.svg new file mode 100644 index 0000000..8ba817e --- /dev/null +++ b/web/src/assets/icons/feather/sidebar.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/skip-back.svg b/web/src/assets/icons/feather/skip-back.svg new file mode 100644 index 0000000..88d024e --- /dev/null +++ b/web/src/assets/icons/feather/skip-back.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/skip-forward.svg b/web/src/assets/icons/feather/skip-forward.svg new file mode 100644 index 0000000..f3fdac3 --- /dev/null +++ b/web/src/assets/icons/feather/skip-forward.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/slack.svg b/web/src/assets/icons/feather/slack.svg new file mode 100644 index 0000000..5d97346 --- /dev/null +++ b/web/src/assets/icons/feather/slack.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/slash.svg b/web/src/assets/icons/feather/slash.svg new file mode 100644 index 0000000..f4131b8 --- /dev/null +++ b/web/src/assets/icons/feather/slash.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/sliders.svg b/web/src/assets/icons/feather/sliders.svg new file mode 100644 index 0000000..19c9385 --- /dev/null +++ b/web/src/assets/icons/feather/sliders.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/smartphone.svg b/web/src/assets/icons/feather/smartphone.svg new file mode 100644 index 0000000..0171a95 --- /dev/null +++ b/web/src/assets/icons/feather/smartphone.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/smile.svg b/web/src/assets/icons/feather/smile.svg new file mode 100644 index 0000000..24dc8a2 --- /dev/null +++ b/web/src/assets/icons/feather/smile.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/speaker.svg b/web/src/assets/icons/feather/speaker.svg new file mode 100644 index 0000000..75d5ff9 --- /dev/null +++ b/web/src/assets/icons/feather/speaker.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/square.svg b/web/src/assets/icons/feather/square.svg new file mode 100644 index 0000000..6eabc77 --- /dev/null +++ b/web/src/assets/icons/feather/square.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/star.svg b/web/src/assets/icons/feather/star.svg new file mode 100644 index 0000000..bcdc31a --- /dev/null +++ b/web/src/assets/icons/feather/star.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/stop-circle.svg b/web/src/assets/icons/feather/stop-circle.svg new file mode 100644 index 0000000..c10d9d4 --- /dev/null +++ b/web/src/assets/icons/feather/stop-circle.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/sun.svg b/web/src/assets/icons/feather/sun.svg new file mode 100644 index 0000000..7f51b94 --- /dev/null +++ b/web/src/assets/icons/feather/sun.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/sunrise.svg b/web/src/assets/icons/feather/sunrise.svg new file mode 100644 index 0000000..eff4b1e --- /dev/null +++ b/web/src/assets/icons/feather/sunrise.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/sunset.svg b/web/src/assets/icons/feather/sunset.svg new file mode 100644 index 0000000..a5a2221 --- /dev/null +++ b/web/src/assets/icons/feather/sunset.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/table.svg b/web/src/assets/icons/feather/table.svg new file mode 100644 index 0000000..679bd57 --- /dev/null +++ b/web/src/assets/icons/feather/table.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/tablet.svg b/web/src/assets/icons/feather/tablet.svg new file mode 100644 index 0000000..9c80b40 --- /dev/null +++ b/web/src/assets/icons/feather/tablet.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/tag.svg b/web/src/assets/icons/feather/tag.svg new file mode 100644 index 0000000..7219b15 --- /dev/null +++ b/web/src/assets/icons/feather/tag.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/target.svg b/web/src/assets/icons/feather/target.svg new file mode 100644 index 0000000..be84b17 --- /dev/null +++ b/web/src/assets/icons/feather/target.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/terminal.svg b/web/src/assets/icons/feather/terminal.svg new file mode 100644 index 0000000..af459c0 --- /dev/null +++ b/web/src/assets/icons/feather/terminal.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/thermometer.svg b/web/src/assets/icons/feather/thermometer.svg new file mode 100644 index 0000000..33142cc --- /dev/null +++ b/web/src/assets/icons/feather/thermometer.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/thumbs-down.svg b/web/src/assets/icons/feather/thumbs-down.svg new file mode 100644 index 0000000..3e7bcd6 --- /dev/null +++ b/web/src/assets/icons/feather/thumbs-down.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/thumbs-up.svg b/web/src/assets/icons/feather/thumbs-up.svg new file mode 100644 index 0000000..226c44d --- /dev/null +++ b/web/src/assets/icons/feather/thumbs-up.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/toggle-left.svg b/web/src/assets/icons/feather/toggle-left.svg new file mode 100644 index 0000000..240be29 --- /dev/null +++ b/web/src/assets/icons/feather/toggle-left.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/toggle-right.svg b/web/src/assets/icons/feather/toggle-right.svg new file mode 100644 index 0000000..fc6e81c --- /dev/null +++ b/web/src/assets/icons/feather/toggle-right.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/tool.svg b/web/src/assets/icons/feather/tool.svg new file mode 100644 index 0000000..f3cbf3d --- /dev/null +++ b/web/src/assets/icons/feather/tool.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/trash-2.svg b/web/src/assets/icons/feather/trash-2.svg new file mode 100644 index 0000000..f24d55b --- /dev/null +++ b/web/src/assets/icons/feather/trash-2.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/trash.svg b/web/src/assets/icons/feather/trash.svg new file mode 100644 index 0000000..55650bd --- /dev/null +++ b/web/src/assets/icons/feather/trash.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/trello.svg b/web/src/assets/icons/feather/trello.svg new file mode 100644 index 0000000..b2f599b --- /dev/null +++ b/web/src/assets/icons/feather/trello.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/trending-down.svg b/web/src/assets/icons/feather/trending-down.svg new file mode 100644 index 0000000..a9d4cfa --- /dev/null +++ b/web/src/assets/icons/feather/trending-down.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/trending-up.svg b/web/src/assets/icons/feather/trending-up.svg new file mode 100644 index 0000000..52026a4 --- /dev/null +++ b/web/src/assets/icons/feather/trending-up.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/triangle.svg b/web/src/assets/icons/feather/triangle.svg new file mode 100644 index 0000000..274b652 --- /dev/null +++ b/web/src/assets/icons/feather/triangle.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/truck.svg b/web/src/assets/icons/feather/truck.svg new file mode 100644 index 0000000..3389837 --- /dev/null +++ b/web/src/assets/icons/feather/truck.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/tv.svg b/web/src/assets/icons/feather/tv.svg new file mode 100644 index 0000000..955bbff --- /dev/null +++ b/web/src/assets/icons/feather/tv.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/twitch.svg b/web/src/assets/icons/feather/twitch.svg new file mode 100644 index 0000000..1706249 --- /dev/null +++ b/web/src/assets/icons/feather/twitch.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/twitter.svg b/web/src/assets/icons/feather/twitter.svg new file mode 100644 index 0000000..f8886ec --- /dev/null +++ b/web/src/assets/icons/feather/twitter.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/type.svg b/web/src/assets/icons/feather/type.svg new file mode 100644 index 0000000..c6b2de3 --- /dev/null +++ b/web/src/assets/icons/feather/type.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/umbrella.svg b/web/src/assets/icons/feather/umbrella.svg new file mode 100644 index 0000000..dc77c0c --- /dev/null +++ b/web/src/assets/icons/feather/umbrella.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/underline.svg b/web/src/assets/icons/feather/underline.svg new file mode 100644 index 0000000..044945d --- /dev/null +++ b/web/src/assets/icons/feather/underline.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/unlock.svg b/web/src/assets/icons/feather/unlock.svg new file mode 100644 index 0000000..01dc359 --- /dev/null +++ b/web/src/assets/icons/feather/unlock.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/upload-cloud.svg b/web/src/assets/icons/feather/upload-cloud.svg new file mode 100644 index 0000000..a1db297 --- /dev/null +++ b/web/src/assets/icons/feather/upload-cloud.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/upload.svg b/web/src/assets/icons/feather/upload.svg new file mode 100644 index 0000000..91eaff7 --- /dev/null +++ b/web/src/assets/icons/feather/upload.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/user-check.svg b/web/src/assets/icons/feather/user-check.svg new file mode 100644 index 0000000..42f91b2 --- /dev/null +++ b/web/src/assets/icons/feather/user-check.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/user-minus.svg b/web/src/assets/icons/feather/user-minus.svg new file mode 100644 index 0000000..44b75f5 --- /dev/null +++ b/web/src/assets/icons/feather/user-minus.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/user-plus.svg b/web/src/assets/icons/feather/user-plus.svg new file mode 100644 index 0000000..21460f6 --- /dev/null +++ b/web/src/assets/icons/feather/user-plus.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/user-x.svg b/web/src/assets/icons/feather/user-x.svg new file mode 100644 index 0000000..0c41a48 --- /dev/null +++ b/web/src/assets/icons/feather/user-x.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/user.svg b/web/src/assets/icons/feather/user.svg new file mode 100644 index 0000000..7bb5f29 --- /dev/null +++ b/web/src/assets/icons/feather/user.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/users.svg b/web/src/assets/icons/feather/users.svg new file mode 100644 index 0000000..aacf6b0 --- /dev/null +++ b/web/src/assets/icons/feather/users.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/video-off.svg b/web/src/assets/icons/feather/video-off.svg new file mode 100644 index 0000000..08ec697 --- /dev/null +++ b/web/src/assets/icons/feather/video-off.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/video.svg b/web/src/assets/icons/feather/video.svg new file mode 100644 index 0000000..8ff156a --- /dev/null +++ b/web/src/assets/icons/feather/video.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/voicemail.svg b/web/src/assets/icons/feather/voicemail.svg new file mode 100644 index 0000000..5d78a8e --- /dev/null +++ b/web/src/assets/icons/feather/voicemail.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/volume-1.svg b/web/src/assets/icons/feather/volume-1.svg new file mode 100644 index 0000000..150e875 --- /dev/null +++ b/web/src/assets/icons/feather/volume-1.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/volume-2.svg b/web/src/assets/icons/feather/volume-2.svg new file mode 100644 index 0000000..03d521c --- /dev/null +++ b/web/src/assets/icons/feather/volume-2.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/volume-x.svg b/web/src/assets/icons/feather/volume-x.svg new file mode 100644 index 0000000..be44240 --- /dev/null +++ b/web/src/assets/icons/feather/volume-x.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/volume.svg b/web/src/assets/icons/feather/volume.svg new file mode 100644 index 0000000..53bfe15 --- /dev/null +++ b/web/src/assets/icons/feather/volume.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/watch.svg b/web/src/assets/icons/feather/watch.svg new file mode 100644 index 0000000..a1099da --- /dev/null +++ b/web/src/assets/icons/feather/watch.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/wifi-off.svg b/web/src/assets/icons/feather/wifi-off.svg new file mode 100644 index 0000000..35eae43 --- /dev/null +++ b/web/src/assets/icons/feather/wifi-off.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/wifi.svg b/web/src/assets/icons/feather/wifi.svg new file mode 100644 index 0000000..748c285 --- /dev/null +++ b/web/src/assets/icons/feather/wifi.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/wind.svg b/web/src/assets/icons/feather/wind.svg new file mode 100644 index 0000000..82b3646 --- /dev/null +++ b/web/src/assets/icons/feather/wind.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/x-circle.svg b/web/src/assets/icons/feather/x-circle.svg new file mode 100644 index 0000000..94aad5e --- /dev/null +++ b/web/src/assets/icons/feather/x-circle.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/x-octagon.svg b/web/src/assets/icons/feather/x-octagon.svg new file mode 100644 index 0000000..8543198 --- /dev/null +++ b/web/src/assets/icons/feather/x-octagon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/x-square.svg b/web/src/assets/icons/feather/x-square.svg new file mode 100644 index 0000000..7677c38 --- /dev/null +++ b/web/src/assets/icons/feather/x-square.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/x.svg b/web/src/assets/icons/feather/x.svg new file mode 100644 index 0000000..7d5875c --- /dev/null +++ b/web/src/assets/icons/feather/x.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/youtube.svg b/web/src/assets/icons/feather/youtube.svg new file mode 100644 index 0000000..c482438 --- /dev/null +++ b/web/src/assets/icons/feather/youtube.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/zap-off.svg b/web/src/assets/icons/feather/zap-off.svg new file mode 100644 index 0000000..c636f8b --- /dev/null +++ b/web/src/assets/icons/feather/zap-off.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/zap.svg b/web/src/assets/icons/feather/zap.svg new file mode 100644 index 0000000..8fdafa9 --- /dev/null +++ b/web/src/assets/icons/feather/zap.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/zoom-in.svg b/web/src/assets/icons/feather/zoom-in.svg new file mode 100644 index 0000000..da4572d --- /dev/null +++ b/web/src/assets/icons/feather/zoom-in.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/feather/zoom-out.svg b/web/src/assets/icons/feather/zoom-out.svg new file mode 100644 index 0000000..fd678d7 --- /dev/null +++ b/web/src/assets/icons/feather/zoom-out.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/assets/icons/isme/apifox.svg b/web/src/assets/icons/isme/apifox.svg new file mode 100644 index 0000000..009cdf5 --- /dev/null +++ b/web/src/assets/icons/isme/apifox.svg @@ -0,0 +1,16 @@ + + + diff --git a/web/src/assets/icons/isme/awesome.svg b/web/src/assets/icons/isme/awesome.svg new file mode 100644 index 0000000..cfaab8b --- /dev/null +++ b/web/src/assets/icons/isme/awesome.svg @@ -0,0 +1 @@ + diff --git a/web/src/assets/icons/isme/dialog.svg b/web/src/assets/icons/isme/dialog.svg new file mode 100644 index 0000000..809330d --- /dev/null +++ b/web/src/assets/icons/isme/dialog.svg @@ -0,0 +1 @@ + diff --git a/web/src/assets/icons/isme/docs.svg b/web/src/assets/icons/isme/docs.svg new file mode 100644 index 0000000..907ac11 --- /dev/null +++ b/web/src/assets/icons/isme/docs.svg @@ -0,0 +1,15 @@ + + + diff --git a/web/src/assets/icons/isme/gitee.svg b/web/src/assets/icons/isme/gitee.svg new file mode 100644 index 0000000..5896c65 --- /dev/null +++ b/web/src/assets/icons/isme/gitee.svg @@ -0,0 +1 @@ + diff --git a/web/src/assets/icons/isme/naiveui.svg b/web/src/assets/icons/isme/naiveui.svg new file mode 100644 index 0000000..c236f7f --- /dev/null +++ b/web/src/assets/icons/isme/naiveui.svg @@ -0,0 +1,37 @@ + + + + + + + diff --git a/web/src/assets/images/404.webp b/web/src/assets/images/404.webp new file mode 100644 index 0000000..3482bf9 Binary files /dev/null and b/web/src/assets/images/404.webp differ diff --git a/web/src/assets/images/isme.png b/web/src/assets/images/isme.png new file mode 100644 index 0000000..6a2acca Binary files /dev/null and b/web/src/assets/images/isme.png differ diff --git a/web/src/assets/images/login_banner.webp b/web/src/assets/images/login_banner.webp new file mode 100644 index 0000000..2bc7cad Binary files /dev/null and b/web/src/assets/images/login_banner.webp differ diff --git a/web/src/assets/images/login_bg.webp b/web/src/assets/images/login_bg.webp new file mode 100644 index 0000000..2a9df19 Binary files /dev/null and b/web/src/assets/images/login_bg.webp differ diff --git a/web/src/assets/images/logo.png b/web/src/assets/images/logo.png new file mode 100644 index 0000000..187ff0b Binary files /dev/null and b/web/src/assets/images/logo.png differ diff --git a/web/src/components/common/AppCard.vue b/web/src/components/common/AppCard.vue new file mode 100644 index 0000000..358cf4c --- /dev/null +++ b/web/src/components/common/AppCard.vue @@ -0,0 +1,19 @@ + + + + + diff --git a/web/src/components/common/AppPage.vue b/web/src/components/common/AppPage.vue new file mode 100644 index 0000000..31881b8 --- /dev/null +++ b/web/src/components/common/AppPage.vue @@ -0,0 +1,33 @@ + + + + + diff --git a/web/src/components/common/CommonPage.vue b/web/src/components/common/CommonPage.vue new file mode 100644 index 0000000..1e3c423 --- /dev/null +++ b/web/src/components/common/CommonPage.vue @@ -0,0 +1,76 @@ + + + + + diff --git a/web/src/components/common/LayoutSetting.vue b/web/src/components/common/LayoutSetting.vue new file mode 100644 index 0000000..137493b --- /dev/null +++ b/web/src/components/common/LayoutSetting.vue @@ -0,0 +1,102 @@ + + + + + diff --git a/web/src/components/common/TheFooter.vue b/web/src/components/common/TheFooter.vue new file mode 100644 index 0000000..e2cf27e --- /dev/null +++ b/web/src/components/common/TheFooter.vue @@ -0,0 +1,24 @@ + + + diff --git a/web/src/components/common/TheLogo.vue b/web/src/components/common/TheLogo.vue new file mode 100644 index 0000000..e5a8420 --- /dev/null +++ b/web/src/components/common/TheLogo.vue @@ -0,0 +1,12 @@ + + diff --git a/web/src/components/common/ThemeSetting.vue b/web/src/components/common/ThemeSetting.vue new file mode 100644 index 0000000..55c5cd1 --- /dev/null +++ b/web/src/components/common/ThemeSetting.vue @@ -0,0 +1,23 @@ + + + diff --git a/web/src/components/common/ToggleTheme.vue b/web/src/components/common/ToggleTheme.vue new file mode 100644 index 0000000..ca97e19 --- /dev/null +++ b/web/src/components/common/ToggleTheme.vue @@ -0,0 +1,44 @@ + + + diff --git a/web/src/components/common/index.js b/web/src/components/common/index.js new file mode 100644 index 0000000..14e66b2 --- /dev/null +++ b/web/src/components/common/index.js @@ -0,0 +1,6 @@ +export { default as AppCard } from './AppCard.vue' +export { default as TheFooter } from './TheFooter.vue' +export { default as AppPage } from './AppPage.vue' +export { default as CommonPage } from './CommonPage.vue' +export { default as LayoutSetting } from './LayoutSetting.vue' +export { default as ToggleTheme } from './ToggleTheme.vue' diff --git a/web/src/components/index.js b/web/src/components/index.js new file mode 100644 index 0000000..8621d75 --- /dev/null +++ b/web/src/components/index.js @@ -0,0 +1,2 @@ +export * from './common' +export * from './me' diff --git a/web/src/components/me/crud/QueryItem.vue b/web/src/components/me/crud/QueryItem.vue new file mode 100644 index 0000000..01ba98f --- /dev/null +++ b/web/src/components/me/crud/QueryItem.vue @@ -0,0 +1,35 @@ + + + + + diff --git a/web/src/components/me/crud/index.vue b/web/src/components/me/crud/index.vue new file mode 100644 index 0000000..ae2e60a --- /dev/null +++ b/web/src/components/me/crud/index.vue @@ -0,0 +1,204 @@ + + + + + diff --git a/web/src/components/me/index.js b/web/src/components/me/index.js new file mode 100644 index 0000000..795b613 --- /dev/null +++ b/web/src/components/me/index.js @@ -0,0 +1,3 @@ +export { default as MeModal } from './modal/index.vue' +export { default as MeCrud } from './crud/index.vue' +export { default as MeQueryItem } from './crud/QueryItem.vue' diff --git a/web/src/components/me/modal/index.vue b/web/src/components/me/modal/index.vue new file mode 100644 index 0000000..40b2585 --- /dev/null +++ b/web/src/components/me/modal/index.vue @@ -0,0 +1,191 @@ + + + + + diff --git a/web/src/components/me/modal/utils.js b/web/src/components/me/modal/utils.js new file mode 100644 index 0000000..dcba865 --- /dev/null +++ b/web/src/components/me/modal/utils.js @@ -0,0 +1,72 @@ +/********************************** + * @Author: Ronnie Zhang + * @LastEditor: Ronnie Zhang + * @LastEditTime: 2024/01/13 17:41:26 + * @Email: zclzone@outlook.com + * Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top + **********************************/ + +// 获取元素的CSS样式 +function getCss(element, key) { + return element.currentStyle + ? element.currentStyle[key] + : window.getComputedStyle(element, null)[key] +} + +// 初始化拖拽 +export function initDrag(bar, box) { + if (!bar || !box) + return + const params = { + left: 0, + top: 0, + currentX: 0, + currentY: 0, + flag: false, + } + + if (getCss(box, 'left') !== 'auto') { + params.left = getCss(box, 'left') + } + if (getCss(box, 'top') !== 'auto') { + params.top = getCss(box, 'top') + } + + // 设置触发拖动元素的鼠标样式为移动图标 + bar.style.cursor = 'move' + // 鼠标按下事件处理函数 + bar.onmousedown = function (e) { + params.flag = true // 设置拖拽标志为true + e.preventDefault() // 阻止默认事件 + params.currentX = e.clientX // 鼠标当前位置的X坐标 + params.currentY = e.clientY // 鼠标当前位置的Y坐标 + } + document.onmouseup = function () { + params.flag = false // 设置拖拽标志为false + if (getCss(box, 'left') !== 'auto') { + params.left = getCss(box, 'left') + } + if (getCss(box, 'top') !== 'auto') { + params.top = getCss(box, 'top') + } + } + document.onmousemove = function (e) { + if (e.target !== bar && !params.flag) + return + + e.preventDefault() // 阻止默认事件 + // 如果拖拽标志为true + if (params.flag) { + const nowX = e.clientX // 鼠标当前位置的X坐标 + const nowY = e.clientY // 鼠标当前位置的Y坐标 + const disX = nowX - params.currentX // 鼠标移动的X距离 + const disY = nowY - params.currentY // 鼠标移动的Y距离 + + const left = Number.parseInt(params.left) + disX // 盒子元素的新left值 + const top = Number.parseInt(params.top) + disY // 盒子元素的新top值 + + box.style.left = `${left}px` + box.style.top = `${top}px` + } + } +} diff --git a/web/src/composables/index.js b/web/src/composables/index.js new file mode 100644 index 0000000..2e9b5a1 --- /dev/null +++ b/web/src/composables/index.js @@ -0,0 +1,4 @@ +export * from './useCrud' +export * from './useForm' +export * from './useModal' +export * from './useAliveData' diff --git a/web/src/composables/useAliveData.js b/web/src/composables/useAliveData.js new file mode 100644 index 0000000..bcc2f06 --- /dev/null +++ b/web/src/composables/useAliveData.js @@ -0,0 +1,30 @@ +/********************************** + * @Author: Ronnie Zhang + * @LastEditor: Ronnie Zhang + * @LastEditTime: 2023/12/05 21:22:28 + * @Email: zclzone@outlook.com + * Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top + **********************************/ + +const lastDataMap = new Map() +export function useAliveData(initData = {}, key) { + key = key ?? useRoute().name + const lastData = lastDataMap.get(key) + const aliveData = ref(lastData || { ...initData }) + + watch( + aliveData, + (v) => { + lastDataMap.set(key, v) + }, + { deep: true }, + ) + + return { + aliveData, + reset() { + aliveData.value = { ...initData } + lastDataMap.delete(key) + }, + } +} diff --git a/web/src/composables/useCrud.js b/web/src/composables/useCrud.js new file mode 100644 index 0000000..d3c4425 --- /dev/null +++ b/web/src/composables/useCrud.js @@ -0,0 +1,127 @@ +/********************************** + * @Author: Ronnie Zhang + * @LastEditor: Ronnie Zhang + * @LastEditTime: 2023/12/12 09:03:00 + * @Email: zclzone@outlook.com + * Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top + **********************************/ + +import { useForm, useModal } from '.' + +const ACTIONS = { + view: '查看', + edit: '编辑', + add: '新增', +} + +export function useCrud({ name, initForm = {}, doCreate, doDelete, doUpdate, refresh }) { + const modalAction = ref('') + const [modalRef, okLoading] = useModal() + const [modalFormRef, modalForm, validation] = useForm(initForm) + + /** 新增 */ + function handleAdd(row = {}, title) { + handleOpen({ action: 'add', title, row: { ...initForm, ...row } }) + } + + /** 修改 */ + function handleEdit(row, title) { + handleOpen({ action: 'edit', title, row }) + } + + /** 查看 */ + function handleView(row, title) { + handleOpen({ action: 'view', title, row }) + } + + /** 打开modal */ + function handleOpen(options = {}) { + const { action, row, title, onOk } = options + modalAction.value = action + modalForm.value = { ...row } + modalRef.value?.open({ + ...options, + async onOk() { + if (typeof onOk === 'function') { + return await onOk() + } + else { + return await handleSave() + } + }, + title: title ?? (ACTIONS[modalAction.value] || '') + name, + }) + } + + /** 保存 */ + async function handleSave(action) { + if (!action && !['edit', 'add'].includes(modalAction.value)) { + return false + } + await validation() + const actions = { + add: { + api: () => doCreate(modalForm.value), + cb: () => $message.success('新增成功'), + }, + edit: { + api: () => doUpdate(modalForm.value), + cb: () => $message.success('保存成功'), + }, + } + + action = action || actions[modalAction.value] + + try { + okLoading.value = true + const data = await action.api() + action.cb() + okLoading.value = false + data && refresh(data) + } + catch (error) { + okLoading.value = false + return false + } + } + + /** 删除 */ + function handleDelete(id, confirmOptions) { + if (!id && id !== 0) + return + const d = $dialog.warning({ + content: '确定删除?', + title: '提示', + positiveText: '确定', + negativeText: '取消', + async onPositiveClick() { + try { + d.loading = true + const data = await doDelete(id) + $message.success('删除成功') + d.loading = false + refresh(data, true) + } + catch (error) { + d.loading = false + } + }, + ...confirmOptions, + }) + } + + return { + modalRef, + modalFormRef, + modalAction, + modalForm, + okLoading, + validation, + handleAdd, + handleDelete, + handleEdit, + handleView, + handleOpen, + handleSave, + } +} diff --git a/web/src/composables/useForm.js b/web/src/composables/useForm.js new file mode 100644 index 0000000..69f9d50 --- /dev/null +++ b/web/src/composables/useForm.js @@ -0,0 +1,23 @@ +/********************************** + * @Author: Ronnie Zhang + * @LastEditor: Ronnie Zhang + * @LastEditTime: 2023/12/05 21:22:43 + * @Email: zclzone@outlook.com + * Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top + **********************************/ + +export function useForm(initFormData = {}) { + const formRef = ref(null) + const formModel = ref({ ...initFormData }) + const rules = { + required: { + required: true, + message: '此为必填项', + trigger: ['blur', 'change'], + }, + } + const validation = () => { + return formRef.value?.validate() + } + return [formRef, formModel, validation, rules] +} diff --git a/web/src/composables/useModal.js b/web/src/composables/useModal.js new file mode 100644 index 0000000..dc08216 --- /dev/null +++ b/web/src/composables/useModal.js @@ -0,0 +1,20 @@ +/********************************** + * @Author: Ronnie Zhang + * @LastEditor: Ronnie Zhang + * @LastEditTime: 2023/12/05 21:22:49 + * @Email: zclzone@outlook.com + * Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top + **********************************/ + +export function useModal() { + const modalRef = ref(null) + const okLoading = computed({ + get() { + return modalRef.value?.okLoading + }, + set(v) { + modalRef.value.okLoading = v + }, + }) + return [modalRef, okLoading] +} diff --git a/web/src/directives/index.js b/web/src/directives/index.js new file mode 100644 index 0000000..f27a036 --- /dev/null +++ b/web/src/directives/index.js @@ -0,0 +1,23 @@ +/********************************** + * @Author: Ronnie Zhang + * @LastEditor: Ronnie Zhang + * @LastEditTime: 2023/12/05 21:23:01 + * @Email: zclzone@outlook.com + * Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top + **********************************/ + +import { router } from '@/router' + +const permission = { + mounted(el, binding) { + const currentRoute = unref(router.currentRoute) + const btns = currentRoute.meta?.btns?.map(item => item.code) || [] + if (!btns.includes(binding.value)) { + el.remove() + } + }, +} + +export function setupDirectives(app) { + app.directive('permission', permission) +} diff --git a/web/src/layouts/components/BreadCrumb.vue b/web/src/layouts/components/BreadCrumb.vue new file mode 100644 index 0000000..dadc9ad --- /dev/null +++ b/web/src/layouts/components/BreadCrumb.vue @@ -0,0 +1,86 @@ + + + + + diff --git a/web/src/layouts/components/Fullscreen.vue b/web/src/layouts/components/Fullscreen.vue new file mode 100644 index 0000000..7ccc3d4 --- /dev/null +++ b/web/src/layouts/components/Fullscreen.vue @@ -0,0 +1,13 @@ + + + diff --git a/web/src/layouts/components/MenuCollapse.vue b/web/src/layouts/components/MenuCollapse.vue new file mode 100644 index 0000000..1ec6d30 --- /dev/null +++ b/web/src/layouts/components/MenuCollapse.vue @@ -0,0 +1,22 @@ + + + + + diff --git a/web/src/layouts/components/RoleSelect.vue b/web/src/layouts/components/RoleSelect.vue new file mode 100644 index 0000000..b839df4 --- /dev/null +++ b/web/src/layouts/components/RoleSelect.vue @@ -0,0 +1,90 @@ + + + + + diff --git a/web/src/layouts/components/SideLogo.vue b/web/src/layouts/components/SideLogo.vue new file mode 100644 index 0000000..a9cfba0 --- /dev/null +++ b/web/src/layouts/components/SideLogo.vue @@ -0,0 +1,27 @@ + + + + + diff --git a/web/src/layouts/components/SideMenu.vue b/web/src/layouts/components/SideMenu.vue new file mode 100644 index 0000000..a369658 --- /dev/null +++ b/web/src/layouts/components/SideMenu.vue @@ -0,0 +1,74 @@ + + + + + + + diff --git a/web/src/layouts/components/UserAvatar.vue b/web/src/layouts/components/UserAvatar.vue new file mode 100644 index 0000000..84bf105 --- /dev/null +++ b/web/src/layouts/components/UserAvatar.vue @@ -0,0 +1,85 @@ + + + + + diff --git a/web/src/layouts/components/index.js b/web/src/layouts/components/index.js new file mode 100644 index 0000000..a9d0280 --- /dev/null +++ b/web/src/layouts/components/index.js @@ -0,0 +1,8 @@ +export { default as RoleSelect } from './RoleSelect.vue' +export { default as UserAvatar } from './UserAvatar.vue' +export { default as MenuCollapse } from './MenuCollapse.vue' +export { default as BreadCrumb } from './BreadCrumb.vue' +export { default as AppTab } from './tab/index.vue' +export { default as SideLogo } from './SideLogo.vue' +export { default as SideMenu } from './SideMenu.vue' +export { default as Fullscreen } from './Fullscreen.vue' diff --git a/web/src/layouts/components/tab/ContextMenu.vue b/web/src/layouts/components/tab/ContextMenu.vue new file mode 100644 index 0000000..ceaaae9 --- /dev/null +++ b/web/src/layouts/components/tab/ContextMenu.vue @@ -0,0 +1,125 @@ + + + + + diff --git a/web/src/layouts/components/tab/index.vue b/web/src/layouts/components/tab/index.vue new file mode 100644 index 0000000..0936732 --- /dev/null +++ b/web/src/layouts/components/tab/index.vue @@ -0,0 +1,99 @@ + + + + + + + diff --git a/web/src/layouts/empty/index.vue b/web/src/layouts/empty/index.vue new file mode 100644 index 0000000..31d7e98 --- /dev/null +++ b/web/src/layouts/empty/index.vue @@ -0,0 +1,11 @@ + + + diff --git a/web/src/layouts/full/header/index.vue b/web/src/layouts/full/header/index.vue new file mode 100644 index 0000000..45850d7 --- /dev/null +++ b/web/src/layouts/full/header/index.vue @@ -0,0 +1,43 @@ + + + + + diff --git a/web/src/layouts/full/index.vue b/web/src/layouts/full/index.vue new file mode 100644 index 0000000..24d8d86 --- /dev/null +++ b/web/src/layouts/full/index.vue @@ -0,0 +1,42 @@ + + + + + + + diff --git a/web/src/layouts/full/sidebar/index.vue b/web/src/layouts/full/sidebar/index.vue new file mode 100644 index 0000000..030938e --- /dev/null +++ b/web/src/layouts/full/sidebar/index.vue @@ -0,0 +1,16 @@ + + + + + diff --git a/web/src/layouts/normal/header/index.vue b/web/src/layouts/normal/header/index.vue new file mode 100644 index 0000000..9590e8f --- /dev/null +++ b/web/src/layouts/normal/header/index.vue @@ -0,0 +1,45 @@ + + + + + diff --git a/web/src/layouts/normal/index.vue b/web/src/layouts/normal/index.vue new file mode 100644 index 0000000..12fb6de --- /dev/null +++ b/web/src/layouts/normal/index.vue @@ -0,0 +1,38 @@ + + + + + + + diff --git a/web/src/layouts/normal/sidebar/index.vue b/web/src/layouts/normal/sidebar/index.vue new file mode 100644 index 0000000..f6b71fb --- /dev/null +++ b/web/src/layouts/normal/sidebar/index.vue @@ -0,0 +1,16 @@ + + + + + diff --git a/web/src/layouts/simple/index.vue b/web/src/layouts/simple/index.vue new file mode 100644 index 0000000..ef192dd --- /dev/null +++ b/web/src/layouts/simple/index.vue @@ -0,0 +1,36 @@ + + + + + + + diff --git a/web/src/layouts/simple/sidebar/index.vue b/web/src/layouts/simple/sidebar/index.vue new file mode 100644 index 0000000..27a7e6f --- /dev/null +++ b/web/src/layouts/simple/sidebar/index.vue @@ -0,0 +1,23 @@ + + + + + diff --git a/web/src/main.js b/web/src/main.js new file mode 100644 index 0000000..ce2e92f --- /dev/null +++ b/web/src/main.js @@ -0,0 +1,31 @@ +/********************************** + * @Description: 入口文件 + * @FilePath: main.js + * @Author: Ronnie Zhang + * @LastEditor: Ronnie Zhang + * @LastEditTime: 2023/12/04 22:41:32 + * @Email: zclzone@outlook.com + * Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top + **********************************/ + +import '@/styles/reset.css' +import '@/styles/global.scss' +import 'uno.css' + +import { createApp } from 'vue' +import App from './App.vue' +import { setupRouter } from './router' +import { setupStore } from './store' +import { setupNaiveDiscreteApi } from './utils' +import { setupDirectives } from './directives' + +async function bootstrap() { + const app = createApp(App) + setupStore(app) + setupDirectives(app) + await setupRouter(app) + app.mount('#app') + setupNaiveDiscreteApi() +} + +bootstrap() diff --git a/web/src/router/basic-routes.js b/web/src/router/basic-routes.js new file mode 100644 index 0000000..e8321ab --- /dev/null +++ b/web/src/router/basic-routes.js @@ -0,0 +1,40 @@ +export const basicRoutes = [ + { + name: 'Login', + path: '/login', + component: () => import('@/views/login/index.vue'), + meta: { + title: '登录页', + layout: 'empty', + }, + }, + + { + name: 'Home', + path: '/', + component: () => import('@/views/home/index.vue'), + meta: { + title: '首页', + }, + }, + + { + name: '404', + path: '/404', + component: () => import('@/views/error-page/404.vue'), + meta: { + title: '页面飞走了', + layout: 'empty', + }, + }, + + { + name: '403', + path: '/403', + component: () => import('@/views/error-page/403.vue'), + meta: { + title: '没有权限', + layout: 'empty', + }, + }, +] diff --git a/web/src/router/guards/index.js b/web/src/router/guards/index.js new file mode 100644 index 0000000..35f274b --- /dev/null +++ b/web/src/router/guards/index.js @@ -0,0 +1,19 @@ +/********************************** + * @Author: Ronnie Zhang + * @LastEditor: Ronnie Zhang + * @LastEditTime: 2023/12/05 21:24:46 + * @Email: zclzone@outlook.com + * Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top + **********************************/ + +import { createPageLoadingGuard } from './page-loading-guard' +import { createPageTitleGuard } from './page-title-guard' +import { createPermissionGuard } from './permission-guard' +import { createTabGuard } from './tab-guard' + +export function setupRouterGuards(router) { + createPageLoadingGuard(router) + createPermissionGuard(router) + createPageTitleGuard(router) + createTabGuard(router) +} diff --git a/web/src/router/guards/page-loading-guard.js b/web/src/router/guards/page-loading-guard.js new file mode 100644 index 0000000..ba145fa --- /dev/null +++ b/web/src/router/guards/page-loading-guard.js @@ -0,0 +1,23 @@ +/********************************** + * @Author: Ronnie Zhang + * @LastEditor: Ronnie Zhang + * @LastEditTime: 2023/12/05 21:24:53 + * @Email: zclzone@outlook.com + * Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top + **********************************/ + +export function createPageLoadingGuard(router) { + router.beforeEach(() => { + $loadingBar.start() + }) + + router.afterEach(() => { + setTimeout(() => { + $loadingBar.finish() + }, 200) + }) + + router.onError(() => { + $loadingBar.error() + }) +} diff --git a/web/src/router/guards/page-title-guard.js b/web/src/router/guards/page-title-guard.js new file mode 100644 index 0000000..96042f6 --- /dev/null +++ b/web/src/router/guards/page-title-guard.js @@ -0,0 +1,21 @@ +/********************************** + * @Author: Ronnie Zhang + * @LastEditor: Ronnie Zhang + * @LastEditTime: 2023/12/05 21:25:00 + * @Email: zclzone@outlook.com + * Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top + **********************************/ + +const baseTitle = import.meta.env.VITE_TITLE + +export function createPageTitleGuard(router) { + router.afterEach((to) => { + const pageTitle = to.meta?.title + if (pageTitle) { + document.title = `${pageTitle} | ${baseTitle}` + } + else { + document.title = baseTitle + } + }) +} diff --git a/web/src/router/guards/permission-guard.js b/web/src/router/guards/permission-guard.js new file mode 100644 index 0000000..b317a08 --- /dev/null +++ b/web/src/router/guards/permission-guard.js @@ -0,0 +1,56 @@ +/********************************** + * @Author: Ronnie Zhang + * @LastEditor: Ronnie Zhang + * @LastEditTime: 2023/12/05 21:25:07 + * @Email: zclzone@outlook.com + * Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top + **********************************/ + +import { useAuthStore, usePermissionStore, useUserStore } from '@/store' +import api from '@/api' +import { getPermissions, getUserInfo } from '@/store/helper' + +const WHITE_LIST = ['/login', '/404'] +export function createPermissionGuard(router) { + router.beforeEach(async (to) => { + const authStore = useAuthStore() + const token = authStore.accessToken + + /** 没有token */ + if (!token) { + if (WHITE_LIST.includes(to.path)) + return true + return { path: 'login', query: { ...to.query, redirect: to.path } } + } + + // 有token的情况 + if (to.path === '/login') + return { path: '/' } + if (WHITE_LIST.includes(to.path)) + return true + + const userStore = useUserStore() + const permissionStore = usePermissionStore() + if (!userStore.userInfo) { + const [user, permissions] = await Promise.all([getUserInfo(), getPermissions()]) + userStore.setUser(user) + permissionStore.setPermissions(permissions) + const routeComponents = import.meta.glob('@/views/**/*.vue') + permissionStore.accessRoutes.forEach((route) => { + route.component = routeComponents[route.component] || undefined + !router.hasRoute(route.name) && router.addRoute(route) + }) + return { ...to, replace: true } + } + + const routes = router.getRoutes() + if (routes.find(route => route.name === to.name)) + return true + + // 判断是无权限还是404 + const { data: hasMenu } = await api.validateMenuPath(to.path) + return hasMenu + ? { name: '403', query: { path: to.fullPath }, state: { from: 'permission-guard' } } + : { name: '404', query: { path: to.fullPath } } + }) +} diff --git a/web/src/router/guards/tab-guard.js b/web/src/router/guards/tab-guard.js new file mode 100644 index 0000000..e74b652 --- /dev/null +++ b/web/src/router/guards/tab-guard.js @@ -0,0 +1,24 @@ +/********************************** + * @Author: Ronnie Zhang + * @LastEditor: Ronnie Zhang + * @LastEditTime: 2023/12/05 21:25:17 + * @Email: zclzone@outlook.com + * Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top + **********************************/ + +import { useTabStore } from '@/store' + +export const EXCLUDE_TAB = ['/404', '/403', '/login'] + +export function createTabGuard(router) { + router.afterEach((to) => { + if (EXCLUDE_TAB.includes(to.path)) + return + const tabStore = useTabStore() + const { name, fullPath: path } = to + const title = to.meta?.title + const icon = to.meta?.icon + const keepAlive = to.meta?.keepAlive + tabStore.addTab({ name, path, title, icon, keepAlive }) + }) +} diff --git a/web/src/router/index.js b/web/src/router/index.js new file mode 100644 index 0000000..994157b --- /dev/null +++ b/web/src/router/index.js @@ -0,0 +1,25 @@ +/********************************** + * @Author: Ronnie Zhang + * @LastEditor: Ronnie Zhang + * @LastEditTime: 2023/12/05 21:25:23 + * @Email: zclzone@outlook.com + * Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top + **********************************/ + +import { createRouter, createWebHashHistory, createWebHistory } from 'vue-router' +import { setupRouterGuards } from './guards' +import { basicRoutes } from './basic-routes' + +export const router = createRouter({ + history: + import.meta.env.VITE_USE_HASH === 'true' + ? createWebHashHistory(import.meta.env.VITE_PUBLIC_PATH || '/') + : createWebHistory(import.meta.env.VITE_PUBLIC_PATH || '/'), + routes: basicRoutes, + scrollBehavior: () => ({ left: 0, top: 0 }), +}) + +export async function setupRouter(app) { + app.use(router) + setupRouterGuards(router) +} diff --git a/web/src/settings.js b/web/src/settings.js new file mode 100644 index 0000000..b337449 --- /dev/null +++ b/web/src/settings.js @@ -0,0 +1,77 @@ +/********************************** + * @Author: Ronnie Zhang + * @LastEditor: Ronnie Zhang + * @LastEditTime: 2023/12/13 20:54:36 + * @Email: zclzone@outlook.com + * Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top + **********************************/ + +export const defaultLayout = 'normal' + +export const defaultPrimaryColor = '#316C72' + +// 控制 LayoutSetting 组件是否可见 +export const layoutSettingVisible = true + +export const naiveThemeOverrides = { + common: { + primaryColor: '#316C72FF', + primaryColorHover: '#316C72E3', + primaryColorPressed: '#2B4C59FF', + primaryColorSuppl: '#316C72E3', + }, +} + +export const basePermissions = [ + { + code: 'ExternalLink', + name: '外链(可内嵌打开)', + type: 'MENU', + icon: 'i-fe:external-link', + order: 98, + enable: true, + show: true, + children: [ + { + code: 'ShowDocs', + name: '项目文档', + type: 'MENU', + path: 'https://docs.isme.top/web/#/624306705/188522224', + icon: 'i-me:docs', + order: 1, + enable: true, + show: true, + }, + { + code: 'ApiFoxDocs', + name: '接口文档', + type: 'MENU', + path: 'https://apifox.com/apidoc/shared-ff4a4d32-c0d1-4caf-b0ee-6abc130f734a', + icon: 'i-me:apifox', + order: 2, + enable: true, + show: true, + }, + { + code: 'NaiveUI', + name: 'Naive UI', + type: 'MENU', + path: 'https://www.naiveui.com/zh-CN/os-theme', + icon: 'i-me:naiveui', + order: 3, + enable: true, + show: true, + }, + { + code: 'MyBlog', + name: '博客-掘金', + type: 'MENU', + path: 'https://juejin.cn/user/1961184475483255/posts', + icon: 'i-simple-icons:juejin', + order: 4, + enable: true, + show: true, + }, + ], + }, +] diff --git a/web/src/store/helper.js b/web/src/store/helper.js new file mode 100644 index 0000000..dd8fd26 --- /dev/null +++ b/web/src/store/helper.js @@ -0,0 +1,30 @@ +import { basePermissions } from '@/settings' +import api from '@/api' + +export async function getUserInfo() { + const res = await api.getUser() + const { id, username, profile, roles, currentRole } = res.data || {} + return { + id, + username, + avatar: profile?.avatar, + nickName: profile?.nickName, + gender: profile?.gender, + address: profile?.address, + email: profile?.email, + roles, + currentRole, + } +} + +export async function getPermissions() { + let asyncPermissions = [] + try { + const res = await api.getRolePermissions() + asyncPermissions = res?.data || [] + } + catch (error) { + console.error(error) + } + return basePermissions.concat(asyncPermissions) +} diff --git a/web/src/store/index.js b/web/src/store/index.js new file mode 100644 index 0000000..a193337 --- /dev/null +++ b/web/src/store/index.js @@ -0,0 +1,18 @@ +/********************************** + * @Author: Ronnie Zhang + * @LastEditor: Ronnie Zhang + * @LastEditTime: 2023/12/05 21:26:15 + * @Email: zclzone@outlook.com + * Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top + **********************************/ + +import { createPinia } from 'pinia' +import piniaPluginPersistedstate from 'pinia-plugin-persistedstate' + +export function setupStore(app) { + const pinia = createPinia() + pinia.use(piniaPluginPersistedstate) + app.use(pinia) +} + +export * from './modules' diff --git a/web/src/store/modules/app.js b/web/src/store/modules/app.js new file mode 100644 index 0000000..d16aca3 --- /dev/null +++ b/web/src/store/modules/app.js @@ -0,0 +1,56 @@ +/********************************** + * @Author: Ronnie Zhang + * @LastEditor: Ronnie Zhang + * @LastEditTime: 2023/12/05 21:25:31 + * @Email: zclzone@outlook.com + * Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top + **********************************/ + +import { defineStore } from 'pinia' +import { useDark } from '@vueuse/core' +import { generate, getRgbStr } from '@arco-design/color' +import { defaultLayout, defaultPrimaryColor, naiveThemeOverrides } from '@/settings' + +export const useAppStore = defineStore('app', { + state: () => ({ + collapsed: false, + isDark: useDark(), + layout: defaultLayout, + primaryColor: defaultPrimaryColor, + naiveThemeOverrides, + }), + actions: { + switchCollapsed() { + this.collapsed = !this.collapsed + }, + setCollapsed(b) { + this.collapsed = b + }, + toggleDark() { + this.isDark = !this.isDark + }, + setLayout(v) { + this.layout = v + }, + setPrimaryColor(color) { + this.primaryColor = color + }, + setThemeColor(color = this.primaryColor, isDark = this.isDark) { + const colors = generate(color, { + list: true, + dark: isDark, + }) + document.body.style.setProperty('--primary-color', getRgbStr(colors[5])) + this.naiveThemeOverrides.common = Object.assign(this.naiveThemeOverrides.common || {}, { + primaryColor: colors[5], + primaryColorHover: colors[4], + primaryColorSuppl: colors[4], + primaryColorPressed: colors[6], + }) + }, + }, + persist: { + paths: ['collapsed', 'layout', 'primaryColor', 'naiveThemeOverrides'], + storage: sessionStorage, + }, +}) diff --git a/web/src/store/modules/auth.js b/web/src/store/modules/auth.js new file mode 100644 index 0000000..aea8f0e --- /dev/null +++ b/web/src/store/modules/auth.js @@ -0,0 +1,59 @@ +/********************************** + * @Author: Ronnie Zhang + * @LastEditor: Ronnie Zhang + * @LastEditTime: 2023/12/05 21:25:39 + * @Email: zclzone@outlook.com + * Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top + **********************************/ + +import { defineStore } from 'pinia' +import { usePermissionStore, useRouterStore, useTabStore, useUserStore } from '@/store' + +export const useAuthStore = defineStore('auth', { + state: () => ({ + accessToken: undefined, + }), + actions: { + setToken({ accessToken }) { + this.accessToken = accessToken + }, + resetToken() { + this.$reset() + }, + toLogin() { + const { router, route } = useRouterStore() + router.replace({ + path: '/login', + query: route.query, + }) + }, + async switchCurrentRole(data) { + this.resetLoginState() + await nextTick() + this.setToken(data) + }, + resetLoginState() { + const { resetUser } = useUserStore() + const { resetRouter } = useRouterStore() + const { resetPermission, accessRoutes } = usePermissionStore() + const { resetTabs } = useTabStore() + // 重置路由 + resetRouter(accessRoutes) + // 重置用户 + resetUser() + // 重置权限 + resetPermission() + // 重置Tabs + resetTabs() + // 重置token + this.resetToken() + }, + async logout() { + this.resetLoginState() + this.toLogin() + }, + }, + persist: { + key: 'vue-naivue-admin_auth', + }, +}) diff --git a/web/src/store/modules/index.js b/web/src/store/modules/index.js new file mode 100644 index 0000000..9672b79 --- /dev/null +++ b/web/src/store/modules/index.js @@ -0,0 +1,6 @@ +export * from './app' +export * from './auth' +export * from './permission' +export * from './tab' +export * from './user' +export * from './router' diff --git a/web/src/store/modules/permission.js b/web/src/store/modules/permission.js new file mode 100644 index 0000000..b61a039 --- /dev/null +++ b/web/src/store/modules/permission.js @@ -0,0 +1,82 @@ +/********************************** + * @Author: Ronnie Zhang + * @LastEditor: Ronnie Zhang + * @LastEditTime: 2023/12/05 21:25:47 + * @Email: zclzone@outlook.com + * Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top + **********************************/ + +import { hyphenate } from '@vueuse/core' +import { defineStore } from 'pinia' +import { isExternal } from '@/utils' + +export const usePermissionStore = defineStore('permission', { + state: () => ({ + accessRoutes: [], + permissions: [], + menus: [], + }), + actions: { + setPermissions(permissions) { + this.permissions = permissions + this.menus = this.permissions + .filter(item => item.type === 'MENU') + .map(item => this.getMenuItem(item)) + .filter(item => !!item) + .sort((a, b) => a.order - b.order) + }, + getMenuItem(item, parent) { + const route = this.generateRoute(item, item.show ? null : parent?.key) + if (item.enable && route.path && !route.path.startsWith('http')) + this.accessRoutes.push(route) + if (!item.show) + return null + const menuItem = { + label: route.meta.title, + key: route.name, + path: route.path, + originPath: route.meta.originPath, + icon: () => h('i', { class: `${route.meta.icon} text-16` }), + order: item.order ?? 0, + } + const children = item.children?.filter(item => item.type === 'MENU') || [] + if (children.length) { + menuItem.children = children + .map(child => this.getMenuItem(child, menuItem)) + .filter(item => !!item) + .sort((a, b) => a.order - b.order) + if (!menuItem.children.length) + delete menuItem.children + } + return menuItem + }, + generateRoute(item, parentKey) { + let originPath + if (isExternal(item.path)) { + originPath = item.path + item.component = '/src/views/iframe/index.vue' + item.path = `/iframe/${hyphenate(item.code)}` + } + return { + name: item.code, + path: item.path, + redirect: item.redirect, + component: item.component, + meta: { + originPath, + icon: `${item.icon}?mask`, + title: item.name, + layout: item.layout, + keepAlive: !!item.keepAlive, + parentKey, + btns: item.children + ?.filter(item => item.type === 'BUTTON') + .map(item => ({ code: item.code, name: item.name })), + }, + } + }, + resetPermission() { + this.$reset() + }, + }, +}) diff --git a/web/src/store/modules/router.js b/web/src/store/modules/router.js new file mode 100644 index 0000000..51a5b59 --- /dev/null +++ b/web/src/store/modules/router.js @@ -0,0 +1,26 @@ +/********************************** + * @Author: Ronnie Zhang + * @LastEditor: Ronnie Zhang + * @LastEditTime: 2024/01/06 17:18:40 + * @Email: zclzone@outlook.com + * Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top + **********************************/ + +import { defineStore } from 'pinia' + +export const useRouterStore = defineStore('router', () => { + const router = useRouter() + const route = useRoute() + + function resetRouter(accessRoutes) { + accessRoutes.forEach((item) => { + router.hasRoute(item.name) && router.removeRoute(item.name) + }) + } + + return { + router, + route, + resetRouter, + } +}) diff --git a/web/src/store/modules/tab.js b/web/src/store/modules/tab.js new file mode 100644 index 0000000..12c5e46 --- /dev/null +++ b/web/src/store/modules/tab.js @@ -0,0 +1,94 @@ +/********************************** + * @Author: Ronnie Zhang + * @LastEditor: Ronnie Zhang + * @LastEditTime: 2023/12/05 21:25:52 + * @Email: zclzone@outlook.com + * Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top + **********************************/ + +import { defineStore } from 'pinia' +import { useRouterStore } from './router' + +export const useTabStore = defineStore('tab', { + state: () => ({ + tabs: [], + activeTab: '', + reloading: false, + }), + getters: { + activeIndex() { + return this.tabs.findIndex(item => item.path === this.activeTab) + }, + }, + actions: { + async setActiveTab(path) { + await nextTick() // tab栏dom更新完再设置激活,让tab栏定位到新增的tab上生效 + this.activeTab = path + }, + setTabs(tabs) { + this.tabs = tabs + }, + addTab(tab = {}) { + const findIndex = this.tabs.findIndex(item => item.path === tab.path) + if (findIndex !== -1) { + this.tabs.splice(findIndex, 1, tab) + } + else { + this.setTabs([...this.tabs, tab]) + } + this.setActiveTab(tab.path) + }, + async reloadTab(path, keepAlive) { + const findItem = this.tabs.find(item => item.path === path) + if (!findItem) + return + // 更新key可让keepAlive失效 + if (keepAlive) + findItem.keepAlive = false + $loadingBar.start() + this.reloading = true + await nextTick() + this.reloading = false + findItem.keepAlive = !!keepAlive + setTimeout(() => { + document.documentElement.scrollTo({ left: 0, top: 0 }) + $loadingBar.finish() + }, 100) + }, + async removeTab(path) { + this.setTabs(this.tabs.filter(tab => tab.path !== path)) + if (path === this.activeTab) { + useRouterStore().router?.push(this.tabs[this.tabs.length - 1].path) + } + }, + removeOther(curPath = this.activeTab) { + this.setTabs(this.tabs.filter(tab => tab.path === curPath)) + if (curPath !== this.activeTab) { + useRouterStore().router?.push(this.tabs[this.tabs.length - 1].path) + } + }, + removeLeft(curPath) { + const curIndex = this.tabs.findIndex(item => item.path === curPath) + const filterTabs = this.tabs.filter((item, index) => index >= curIndex) + this.setTabs(filterTabs) + if (!filterTabs.find(item => item.path === this.activeTab)) { + useRouterStore().router?.push(filterTabs[filterTabs.length - 1].path) + } + }, + removeRight(curPath) { + const curIndex = this.tabs.findIndex(item => item.path === curPath) + const filterTabs = this.tabs.filter((item, index) => index <= curIndex) + this.setTabs(filterTabs) + if (!filterTabs.find(item => item.path === this.activeTab.value)) { + useRouterStore().router?.push(filterTabs[filterTabs.length - 1].path) + } + }, + resetTabs() { + this.$reset() + }, + }, + persist: { + paths: ['tabs'], + storage: sessionStorage, + }, +}) diff --git a/web/src/store/modules/user.js b/web/src/store/modules/user.js new file mode 100644 index 0000000..c434737 --- /dev/null +++ b/web/src/store/modules/user.js @@ -0,0 +1,43 @@ +/********************************** + * @Author: Ronnie Zhang + * @LastEditor: Ronnie Zhang + * @LastEditTime: 2023/12/05 21:25:59 + * @Email: zclzone@outlook.com + * Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top + **********************************/ + +import { defineStore } from 'pinia' + +export const useUserStore = defineStore('user', { + state: () => ({ + userInfo: null, + }), + getters: { + userId() { + return this.userInfo?.id + }, + username() { + return this.userInfo?.username + }, + nickName() { + return this.userInfo?.nickName + }, + avatar() { + return this.userInfo?.avatar + }, + currentRole() { + return this.userInfo?.currentRole || {} + }, + roles() { + return this.userInfo?.roles || [] + }, + }, + actions: { + setUser(user) { + this.userInfo = user + }, + resetUser() { + this.$reset() + }, + }, +}) diff --git a/web/src/styles/global.scss b/web/src/styles/global.scss new file mode 100644 index 0000000..857043c --- /dev/null +++ b/web/src/styles/global.scss @@ -0,0 +1,91 @@ +/********************************** + * @Author: Ronnie Zhang + * @LastEditor: Ronnie Zhang + * @LastEditTime: 2023/12/05 21:26:28 + * @Email: zclzone@outlook.com + * Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top + **********************************/ + +html, +body { + width: 100%; + height: 100%; + overflow: hidden; +} + +#app { + width: 100%; + height: 100%; +} + +/* transition fade-slide */ +.fade-slide-leave-active, +.fade-slide-enter-active { + transition: all 0.3s; +} + +.fade-slide-enter-from { + opacity: 0; + transform: translateX(-30px); +} + +.fade-slide-leave-to { + opacity: 0; + transform: translateX(30px); +} + +/* 自定义滚动条样式 */ +.cus-scroll { + overflow: auto; + &::-webkit-scrollbar { + width: 8px; + height: 8px; + } +} +.cus-scroll-x { + overflow-x: auto; + &::-webkit-scrollbar { + width: 0; + height: 8px; + } +} +.cus-scroll-y { + overflow-y: auto; + &::-webkit-scrollbar { + width: 8px; + height: 0; + } +} +.cus-scroll, +.cus-scroll-x, +.cus-scroll-y { + &::-webkit-scrollbar-thumb { + background-color: transparent; + border-radius: 4px; + } + &:hover { + &::-webkit-scrollbar-thumb { + background: #bfbfbf; + } + &::-webkit-scrollbar-thumb:hover { + background: rgb(var(--primary-color)); + } + } +} + +/* 切换主题的动画效果 */ +::view-transition-old(root), +::view-transition-new(root) { + animation: none; + mix-blend-mode: normal; +} + +::view-transition-old(root), +.dark::view-transition-new(root) { + z-index: 1; +} + +::view-transition-new(root), +.dark::view-transition-old(root) { + z-index: 9999; +} diff --git a/web/src/styles/reset.css b/web/src/styles/reset.css new file mode 100644 index 0000000..71447a2 --- /dev/null +++ b/web/src/styles/reset.css @@ -0,0 +1,49 @@ +/********************************** + * @Author: Ronnie Zhang + * @LastEditor: Ronnie Zhang + * @LastEditTime: 2023/12/05 21:26:38 + * @Email: zclzone@outlook.com + * Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top + **********************************/ + +html { + box-sizing: border-box; +} + +*, +::before, +::after { + margin: 0; + padding: 0; + box-sizing: inherit; +} + +a { + text-decoration: none; + color: inherit; +} + +a:hover, +a:link, +a:visited, +a:active { + text-decoration: none; +} + +ol, +ul { + list-style: none; +} + +input, +textarea { + outline: none; + border: none; + resize: none; +} + +img, +video { + max-width: 100%; + height: auto; +} diff --git a/web/src/utils/common.js b/web/src/utils/common.js new file mode 100644 index 0000000..eccf9e9 --- /dev/null +++ b/web/src/utils/common.js @@ -0,0 +1,106 @@ +/********************************** + * @FilePath: common.js + * @Author: Ronnie Zhang + * @LastEditor: Ronnie Zhang + * @LastEditTime: 2023/12/04 22:45:46 + * @Email: zclzone@outlook.com + * Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top + **********************************/ + +import dayjs from 'dayjs' + +/** + * @param {(object | string | number)} time + * @param {string} format + * @returns {string | null} 格式化后的时间字符串 + * + */ +export function formatDateTime(time = undefined, format = 'YYYY-MM-DD HH:mm:ss') { + return dayjs(time).format(format) +} + +export function formatDate(date = undefined, format = 'YYYY-MM-DD') { + return formatDateTime(date, format) +} + +/** + * @param {Function} fn + * @param {number} wait + * @returns {Function} 节流函数 + * + */ +export function throttle(fn, wait) { + let context, args + let previous = 0 + + return function (...argArr) { + const now = +new Date() + context = this + args = argArr + if (now - previous > wait) { + fn.apply(context, args) + previous = now + } + } +} + +/** + * @param {Function} method + * @param {number} wait + * @param {boolean} immediate + * @return {*} 防抖函数 + */ +export function debounce(method, wait, immediate) { + let timeout + return function (...args) { + const context = this + if (timeout) { + clearTimeout(timeout) + } + // 立即执行需要两个条件,一是immediate为true,二是timeout未被赋值或被置为null + if (immediate) { + /** + * 如果定时器不存在,则立即执行,并设置一个定时器,wait毫秒后将定时器置为null + * 这样确保立即执行后wait毫秒内不会被再次触发 + */ + const callNow = !timeout + timeout = setTimeout(() => { + timeout = null + }, wait) + if (callNow) { + method.apply(context, args) + } + } + else { + // 如果immediate为false,则函数wait毫秒后执行 + timeout = setTimeout(() => { + /** + * args是一个类数组对象,所以使用fn.apply + * 也可写作method.call(context, ...args) + */ + method.apply(context, args) + }, wait) + } + } +} + +/** + * @param {number} time 毫秒数 + * @returns 睡一会儿,让子弹暂停一下 + */ +export function sleep(time) { + return new Promise(resolve => setTimeout(resolve, time)) +} + +/** + * @param {HTMLElement} el + * @param {Function} cb + * @return {ResizeObserver} + */ +export function useResize(el, cb) { + const observer = new ResizeObserver((entries) => { + cb(entries[0].contentRect) + }) + observer.observe(el) + return observer +} diff --git a/web/src/utils/http/helpers.js b/web/src/utils/http/helpers.js new file mode 100644 index 0000000..b7de8bb --- /dev/null +++ b/web/src/utils/http/helpers.js @@ -0,0 +1,67 @@ +/********************************** + * @FilePath: helpers.js + * @Author: Ronnie Zhang + * @LastEditor: Ronnie Zhang + * @LastEditTime: 2023/12/04 22:46:22 + * @Email: zclzone@outlook.com + * Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top + **********************************/ + +import { useAuthStore } from '@/store' + +let isConfirming = false +export function resolveResError(code, message, needTip = true) { + switch (code) { + case 401: + if (isConfirming || !needTip) + return + isConfirming = true + $dialog.confirm({ + title: '提示', + type: 'info', + content: '登录已过期,是否重新登录?', + confirm() { + useAuthStore().logout() + window.$message?.success('已退出登录') + isConfirming = false + }, + cancel() { + isConfirming = false + }, + }) + return false + case 11007: + case 11008: + if (isConfirming || !needTip) + return + isConfirming = true + $dialog.confirm({ + title: '提示', + type: 'info', + content: `${message},是否重新登录?`, + confirm() { + useAuthStore().logout() + window.$message?.success('已退出登录') + isConfirming = false + }, + cancel() { + isConfirming = false + }, + }) + return false + case 403: + message = '请求被拒绝' + break + case 404: + message = '请求资源或接口不存在' + break + case 500: + message = '服务器发生异常' + break + default: + message = message ?? `【${code}】: 未知异常!` + break + } + needTip && window.$message?.error(message) + return message +} diff --git a/web/src/utils/http/index.js b/web/src/utils/http/index.js new file mode 100644 index 0000000..b0d5ca0 --- /dev/null +++ b/web/src/utils/http/index.js @@ -0,0 +1,30 @@ +/********************************** + * @FilePath: index.js + * @Author: Ronnie Zhang + * @LastEditor: Ronnie Zhang + * @LastEditTime: 2023/12/04 22:46:28 + * @Email: zclzone@outlook.com + * Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top + **********************************/ + +import axios from 'axios' +import { setupInterceptors } from './interceptors' + +export function createAxios(options = {}) { + const defaultOptions = { + baseURL: import.meta.env.VITE_AXIOS_BASE_URL, + timeout: 12000, + } + const service = axios.create({ + ...defaultOptions, + ...options, + }) + setupInterceptors(service) + return service +} + +export const request = createAxios() + +export const mockRequest = createAxios({ + baseURL: '/mock-api', +}) diff --git a/web/src/utils/http/interceptors.js b/web/src/utils/http/interceptors.js new file mode 100644 index 0000000..d048d3d --- /dev/null +++ b/web/src/utils/http/interceptors.js @@ -0,0 +1,70 @@ +/********************************** + * @FilePath: interceptors.js + * @Author: Ronnie Zhang + * @LastEditor: Ronnie Zhang + * @LastEditTime: 2023/12/04 22:46:40 + * @Email: zclzone@outlook.com + * Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top + **********************************/ + +import { resolveResError } from './helpers' +import { useAuthStore } from '@/store' + +export function setupInterceptors(axiosInstance) { + function reqResolve(config) { + // 处理不需要token的请求 + if (config.needToken === false) { + return config + } + + const { accessToken } = useAuthStore() + if (accessToken) { + // token: Bearer + xxx + config.headers.Authorization = `Bearer ${accessToken}` + } + + return config + } + + function reqReject(error) { + return Promise.reject(error) + } + + const SUCCESS_CODES = [0, 200] + function resResolve(response) { + const { data, status, config, statusText, headers } = response + if (headers['content-type']?.includes('json')) { + if (SUCCESS_CODES.includes(data?.code)) { + return Promise.resolve(data) + } + const code = data?.code ?? status + + const needTip = config?.needTip !== false + + // 根据code处理对应的操作,并返回处理后的message + const message = resolveResError(code, data?.message ?? statusText, needTip) + + return Promise.reject({ code, message, error: data ?? response }) + } + return Promise.resolve(data ?? response) + } + + async function resReject(error) { + if (!error || !error.response) { + const code = error?.code + /** 根据code处理对应的操作,并返回处理后的message */ + const message = resolveResError(code, error.message) + return Promise.reject({ code, message, error }) + } + + const { data, status, config } = error.response + const code = data?.code ?? status + + const needTip = config?.needTip !== false + const message = resolveResError(code, data?.message ?? error.message, needTip) + return Promise.reject({ code, message, error: error.response?.data || error.response }) + } + + axiosInstance.interceptors.request.use(reqResolve, reqReject) + axiosInstance.interceptors.response.use(resResolve, resReject) +} diff --git a/web/src/utils/index.js b/web/src/utils/index.js new file mode 100644 index 0000000..a18642a --- /dev/null +++ b/web/src/utils/index.js @@ -0,0 +1,14 @@ +/********************************** + * @FilePath: index.js + * @Author: Ronnie Zhang + * @LastEditor: Ronnie Zhang + * @LastEditTime: 2023/12/04 22:45:53 + * @Email: zclzone@outlook.com + * Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top + **********************************/ + +export * from './common' +export * from './http' +export * from './is' +export * from './naiveTools' +export * from './storage' diff --git a/web/src/utils/is.js b/web/src/utils/is.js new file mode 100644 index 0000000..6b9a814 --- /dev/null +++ b/web/src/utils/is.js @@ -0,0 +1,127 @@ +/********************************** + * @FilePath: is.js + * @Author: Ronnie Zhang + * @LastEditor: Ronnie Zhang + * @LastEditTime: 2023/12/04 22:45:32 + * @Email: zclzone@outlook.com + * Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top + **********************************/ + +const toString = Object.prototype.toString + +export function is(val, type) { + return toString.call(val) === `[object ${type}]` +} + +export function isDef(val) { + return typeof val !== 'undefined' +} + +export function isUndef(val) { + return typeof val === 'undefined' +} + +export function isNull(val) { + return val === null +} + +export function isWhitespace(val) { + return val === '' +} + +export function isObject(val) { + return !isNull(val) && is(val, 'Object') +} + +export function isArray(val) { + return val && Array.isArray(val) +} + +export function isString(val) { + return is(val, 'String') +} + +export function isNumber(val) { + return is(val, 'Number') +} + +export function isBoolean(val) { + return is(val, 'Boolean') +} + +export function isDate(val) { + return is(val, 'Date') +} + +export function isRegExp(val) { + return is(val, 'RegExp') +} + +export function isFunction(val) { + return typeof val === 'function' +} + +export function isPromise(val) { + return is(val, 'Promise') && isObject(val) && isFunction(val.then) && isFunction(val.catch) +} + +export function isElement(val) { + return isObject(val) && !!val.tagName +} + +export function isWindow(val) { + return typeof window !== 'undefined' && isDef(window) && is(val, 'Window') +} + +export function isNullOrUndef(val) { + return isNull(val) || isUndef(val) +} + +export function isNullOrWhitespace(val) { + return isNullOrUndef(val) || isWhitespace(val) +} + +/** 空数组 | 空字符串 | 空对象 | 空Map | 空Set */ +export function isEmpty(val) { + if (isArray(val) || isString(val)) { + return val.length === 0 + } + + if (val instanceof Map || val instanceof Set) { + return val.size === 0 + } + + if (isObject(val)) { + return Object.keys(val).length === 0 + } + + return false +} + +/** + * 类似mysql的IFNULL函数 + * + * @param {number | boolean | string} val + * @param {number | boolean | string} def + * @returns 第一个参数为null | undefined | '' 则返回第二个参数作为备用值,否则返回第一个参数 + */ +export function ifNull(val, def = '') { + return isNullOrWhitespace(val) ? def : val +} + +export function isUrl(path) { + const reg = /^https?:\/\/[-\w+&@#/%?=~|!:,.;]+[-\w+&@#/%=~|]$/ + return reg.test(path) +} + +/** + * @param {string} path + * @returns {boolean} 是否是外部链接 + */ +export function isExternal(path) { + return /^https?:|mailto:|tel:/.test(path) +} + +export const isServer = typeof window === 'undefined' + +export const isClient = !isServer diff --git a/web/src/utils/naiveTools.js b/web/src/utils/naiveTools.js new file mode 100644 index 0000000..20efe5e --- /dev/null +++ b/web/src/utils/naiveTools.js @@ -0,0 +1,121 @@ +/********************************** + * @FilePath: naiveTools.js + * @Author: Ronnie Zhang + * @LastEditor: Ronnie Zhang + * @LastEditTime: 2023/12/04 22:45:20 + * @Email: zclzone@outlook.com + * Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top + **********************************/ + +import * as NaiveUI from 'naive-ui' +import { isNullOrUndef } from '@/utils' +import { useAppStore } from '@/store' + +export function setupMessage(NMessage) { + class Message { + static instance + constructor() { + // 单例模式 + if (Message.instance) + return Message.instance + Message.instance = this + this.message = {} + this.removeTimer = {} + } + + removeMessage(key, duration = 5000) { + this.removeTimer[key] && clearTimeout(this.removeTimer[key]) + this.removeTimer[key] = setTimeout(() => { + this.message[key]?.destroy() + }, duration) + } + + destroy(key, duration = 200) { + setTimeout(() => { + this.message[key]?.destroy() + }, duration) + } + + showMessage(type, content, option = {}) { + if (Array.isArray(content)) { + return content.forEach(msg => NMessage[type](msg, option)) + } + + if (!option.key) { + return NMessage[type](content, option) + } + + const currentMessage = this.message[option.key] + if (currentMessage) { + currentMessage.type = type + currentMessage.content = content + } + else { + this.message[option.key] = NMessage[type](content, { + ...option, + duration: 0, + onAfterLeave: () => { + delete this.message[option.key] + }, + }) + } + this.removeMessage(option.key, option.duration) + } + + loading(content, option) { + this.showMessage('loading', content, option) + } + + success(content, option) { + this.showMessage('success', content, option) + } + + error(content, option) { + this.showMessage('error', content, option) + } + + info(content, option) { + this.showMessage('info', content, option) + } + + warning(content, option) { + this.showMessage('warning', content, option) + } + } + + return new Message() +} + +export function setupDialog(NDialog) { + NDialog.confirm = function (option = {}) { + const showIcon = !isNullOrUndef(option.title) + return NDialog[option.type || 'warning']({ + showIcon, + positiveText: '确定', + negativeText: '取消', + onPositiveClick: option.confirm, + onNegativeClick: option.cancel, + onMaskClick: option.cancel, + ...option, + }) + } + + return NDialog +} + +export function setupNaiveDiscreteApi() { + const appStore = useAppStore() + const configProviderProps = computed(() => ({ + theme: appStore.isDark ? NaiveUI.darkTheme : undefined, + themeOverrides: useAppStore().naiveThemeOverrides, + })) + const { message, dialog, notification, loadingBar } = NaiveUI.createDiscreteApi( + ['message', 'dialog', 'notification', 'loadingBar'], + { configProviderProps }, + ) + + window.$loadingBar = loadingBar + window.$notification = notification + window.$message = setupMessage(message) + window.$dialog = setupDialog(dialog) +} diff --git a/web/src/utils/storage/index.js b/web/src/utils/storage/index.js new file mode 100644 index 0000000..f173867 --- /dev/null +++ b/web/src/utils/storage/index.js @@ -0,0 +1,30 @@ +/********************************** + * @FilePath: index.js + * @Author: Ronnie Zhang + * @LastEditor: Ronnie Zhang + * @LastEditTime: 2023/12/04 22:46:07 + * @Email: zclzone@outlook.com + * Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top + **********************************/ + +import { createStorage } from './storage' + +const prefixKey = 'vue-naive-admin_' + +export const createLocalStorage = function (option = {}) { + return createStorage({ + prefixKey: option.prefixKey || '', + storage: localStorage, + }) +} + +export const createSessionStorage = function (option = {}) { + return createStorage({ + prefixKey: option.prefixKey || '', + storage: sessionStorage, + }) +} + +export const lStorage = createLocalStorage({ prefixKey }) + +export const sStorage = createSessionStorage({ prefixKey }) diff --git a/web/src/utils/storage/storage.js b/web/src/utils/storage/storage.js new file mode 100644 index 0000000..6741e07 --- /dev/null +++ b/web/src/utils/storage/storage.js @@ -0,0 +1,66 @@ +/********************************** + * @FilePath: storage.js + * @Author: Ronnie Zhang + * @LastEditor: Ronnie Zhang + * @LastEditTime: 2023/12/04 22:46:13 + * @Email: zclzone@outlook.com + * Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top + **********************************/ + +import { isNullOrUndef } from '@/utils' + +class Storage { + constructor(option) { + this.storage = option.storage + this.prefixKey = option.prefixKey + } + + getKey(key) { + return `${this.prefixKey}${key}`.toLowerCase() + } + + set(key, value, expire) { + const stringData = JSON.stringify({ + value, + time: Date.now(), + expire: !isNullOrUndef(expire) ? new Date().getTime() + expire * 1000 : null, + }) + this.storage.setItem(this.getKey(key), stringData) + } + + get(key) { + const { value } = this.getItem(key, {}) + return value + } + + getItem(key, def = null) { + const val = this.storage.getItem(this.getKey(key)) + if (!val) + return def + try { + const data = JSON.parse(val) + const { value, time, expire } = data + if (isNullOrUndef(expire) || expire > new Date().getTime()) { + return { value, time } + } + this.remove(key) + return def + } + catch (error) { + this.remove(key) + return def + } + } + + remove(key) { + this.storage.removeItem(this.getKey(key)) + } + + clear() { + this.storage.clear() + } +} + +export function createStorage({ prefixKey = '', storage = sessionStorage }) { + return new Storage({ prefixKey, storage }) +} diff --git a/web/src/views/base/index.vue b/web/src/views/base/index.vue new file mode 100644 index 0000000..d768f38 --- /dev/null +++ b/web/src/views/base/index.vue @@ -0,0 +1,138 @@ + + + + + diff --git a/web/src/views/base/keep-alive.vue b/web/src/views/base/keep-alive.vue new file mode 100644 index 0000000..b268b7b --- /dev/null +++ b/web/src/views/base/keep-alive.vue @@ -0,0 +1,26 @@ + + + + + diff --git a/web/src/views/base/test-modal.vue b/web/src/views/base/test-modal.vue new file mode 100644 index 0000000..2013550 --- /dev/null +++ b/web/src/views/base/test-modal.vue @@ -0,0 +1,73 @@ + + + + + diff --git a/web/src/views/base/unocss-icon.vue b/web/src/views/base/unocss-icon.vue new file mode 100644 index 0000000..8960d8d --- /dev/null +++ b/web/src/views/base/unocss-icon.vue @@ -0,0 +1,44 @@ + + + + + diff --git a/web/src/views/base/unocss.vue b/web/src/views/base/unocss.vue new file mode 100644 index 0000000..980d2f3 --- /dev/null +++ b/web/src/views/base/unocss.vue @@ -0,0 +1,76 @@ + + + diff --git a/web/src/views/demo/upload/index.vue b/web/src/views/demo/upload/index.vue new file mode 100644 index 0000000..9145dd7 --- /dev/null +++ b/web/src/views/demo/upload/index.vue @@ -0,0 +1,97 @@ + + + + + diff --git a/web/src/views/error-page/403.vue b/web/src/views/error-page/403.vue new file mode 100644 index 0000000..880c3de --- /dev/null +++ b/web/src/views/error-page/403.vue @@ -0,0 +1,44 @@ + + + + + diff --git a/web/src/views/error-page/404.vue b/web/src/views/error-page/404.vue new file mode 100644 index 0000000..322aeeb --- /dev/null +++ b/web/src/views/error-page/404.vue @@ -0,0 +1,31 @@ + + + + + diff --git a/web/src/views/home/index.vue b/web/src/views/home/index.vue new file mode 100644 index 0000000..3b5211d --- /dev/null +++ b/web/src/views/home/index.vue @@ -0,0 +1,289 @@ + + + + + diff --git a/web/src/views/iframe/index.vue b/web/src/views/iframe/index.vue new file mode 100644 index 0000000..8768865 --- /dev/null +++ b/web/src/views/iframe/index.vue @@ -0,0 +1,9 @@ +