├── src ├── boot │ ├── .gitkeep │ ├── axios.js │ ├── i18n.js │ ├── main.js │ ├── permission.js │ └── permissionWithDynamicRouter.js ├── store │ ├── actions.js │ ├── modules.js │ ├── state.js │ ├── store-flag.d.ts │ ├── getters.js │ ├── index.js │ └── mutations.js ├── i18n │ ├── index.js │ └── en-us │ │ └── index.js ├── components │ ├── 404 │ │ └── NoFound404.vue │ ├── Layout │ │ └── Layout.vue │ ├── LoadingBar │ │ └── LoadingBar.js │ ├── Markdown │ │ └── Markdown.js │ ├── BaseContent │ │ ├── ThumbStyle.js │ │ └── BaseContent.vue │ ├── ECharts │ │ └── EChartsConfig.js │ ├── Toolbar │ │ ├── ToolbarTitle.vue │ │ └── ToolbarItemRight.vue │ ├── Skeleton │ │ └── SkeletonDemo.vue │ ├── Breadcrumbs │ │ ├── BreadcrumbsUtils.js │ │ └── Breadcrumbs.vue │ ├── Menu │ │ ├── BaseMenu.vue │ │ ├── BottomLink.vue │ │ └── BaseMenuItem.vue │ ├── LottieWebCimo │ │ └── LottieWebCimo.vue │ └── TagView │ │ ├── TagViewUtils.js │ │ └── TagView.vue ├── api │ └── UserApi.js ├── assets │ ├── css │ │ ├── main.css │ │ ├── cimo.css │ │ └── transition.css │ └── js │ │ ├── echarts-3.js │ │ ├── echarts-4.js │ │ └── echarts-1.js ├── App.vue ├── css │ └── app.css ├── pages │ ├── home │ │ └── tableDetail.vue │ ├── components │ │ ├── markdown.vue │ │ ├── scrollDemo.vue │ │ ├── tagViewDemo.vue │ │ ├── keepaliveDoc.vue │ │ ├── loadingBar.vue │ │ ├── breadCrumbsDemo.vue │ │ ├── menu3.vue │ │ ├── json.vue │ │ └── cimo.vue │ ├── router │ │ ├── asyncRouterImpl.vue │ │ ├── myMenu.vue │ │ ├── gettingStarted.vue │ │ └── routerConfig.vue │ ├── axios │ │ └── axios.vue │ ├── optimization │ │ ├── VolumeOptimization.vue │ │ └── renderOptimization.vue │ └── lottie │ │ └── lottie.vue ├── router │ ├── constantRoutes.js │ ├── index.js │ └── permissionUtils.js ├── axios │ ├── FetchData.js │ └── AxiosConfig.js ├── quasar.manage.config.js ├── index.template.html ├── utils │ └── CloneUtils.js └── layouts │ └── MainLayout.vue ├── .devTools ├── shell-electron │ ├── .npmignore │ ├── types │ │ └── index.d.ts │ ├── icons │ │ └── 128.png │ ├── src │ │ ├── hook.js │ │ ├── devtools.js │ │ └── backend.js │ ├── bin.js │ ├── webpack.config.js │ ├── index.js │ ├── app.js │ ├── package.json │ ├── server.js │ ├── app.html │ └── README.md └── shell-chrome │ ├── devtools-background.html │ ├── icons │ ├── 128.png │ ├── 16.png │ ├── 48.png │ ├── 128-beta.png │ ├── 128-gray.png │ ├── 128.nuxt.png │ ├── 16-beta.png │ ├── 16-gray.png │ ├── 16.nuxt.png │ ├── 48-beta.png │ ├── 48-gray.png │ └── 48.nuxt.png │ ├── popups │ ├── not-found.html │ ├── enabled.html │ ├── enabled.nuxt.html │ ├── disabled.html │ ├── disabled.nuxt.html │ └── popup.css │ ├── package.json │ ├── devtools.html │ ├── src │ ├── hook.js │ ├── proxy.js │ ├── backend.js │ ├── detector.js │ ├── devtools.js │ ├── background.js │ └── devtools-background.js │ ├── webpack.config.js │ ├── build │ ├── proxy.js │ ├── devtools-background.js │ ├── background.js │ └── detector.js │ └── manifest.json ├── public ├── data │ ├── pay.png │ ├── bird.jpg │ ├── avatar.jpg │ ├── startData.md │ ├── loadingBarData.md │ ├── markdownData.md │ ├── breadcrumbsData.md │ ├── tagViewData.md │ ├── scrollData.md │ ├── iconData.md │ ├── lottieData.md │ ├── menuData.md │ ├── routerData.md │ ├── axiosData.md │ └── keepAliveData.md ├── favicon.ico └── icons │ ├── favicon-16x16.png │ ├── favicon-32x32.png │ ├── favicon-96x96.png │ └── favicon-128x128.png ├── .eslintignore ├── babel.config.js ├── src-electron ├── icons │ ├── icon.icns │ ├── icon.ico │ └── linux-512x512.png ├── electron-flag.d.ts └── main-process │ ├── electron-main.dev.js │ └── electron-main.js ├── .editorconfig ├── .postcssrc.js ├── .yarnrc ├── .gitignore ├── jsconfig.json ├── LICENSE ├── package.json ├── .eslintrc.js └── README.md /src/boot/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.devTools/shell-electron/.npmignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | src 3 | -------------------------------------------------------------------------------- /src/store/actions.js: -------------------------------------------------------------------------------- 1 | const actions = { 2 | 3 | } 4 | 5 | export default actions 6 | -------------------------------------------------------------------------------- /src/store/modules.js: -------------------------------------------------------------------------------- 1 | const modules = { 2 | 3 | } 4 | 5 | export default modules 6 | -------------------------------------------------------------------------------- /public/data/pay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/972784674t/quasar-manage/HEAD/public/data/pay.png -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/972784674t/quasar-manage/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /public/data/bird.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/972784674t/quasar-manage/HEAD/public/data/bird.jpg -------------------------------------------------------------------------------- /src/i18n/index.js: -------------------------------------------------------------------------------- 1 | import enUS from './en-us' 2 | 3 | export default { 4 | 'en-us': enUS 5 | } 6 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | /dist 2 | /src-bex/www 3 | /src-capacitor 4 | /src-cordova 5 | /.quasar 6 | /node_modules 7 | -------------------------------------------------------------------------------- /public/data/avatar.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/972784674t/quasar-manage/HEAD/public/data/avatar.jpg -------------------------------------------------------------------------------- /.devTools/shell-electron/types/index.d.ts: -------------------------------------------------------------------------------- 1 | export function connect(host?: string, port?: number|string): void 2 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | 2 | module.exports = { 3 | presets: [ 4 | '@quasar/babel-preset-app' 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /src/boot/axios.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import axios from 'axios' 3 | 4 | Vue.prototype.$axios = axios 5 | -------------------------------------------------------------------------------- /src-electron/icons/icon.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/972784674t/quasar-manage/HEAD/src-electron/icons/icon.icns -------------------------------------------------------------------------------- /src-electron/icons/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/972784674t/quasar-manage/HEAD/src-electron/icons/icon.ico -------------------------------------------------------------------------------- /public/icons/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/972784674t/quasar-manage/HEAD/public/icons/favicon-16x16.png -------------------------------------------------------------------------------- /public/icons/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/972784674t/quasar-manage/HEAD/public/icons/favicon-32x32.png -------------------------------------------------------------------------------- /public/icons/favicon-96x96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/972784674t/quasar-manage/HEAD/public/icons/favicon-96x96.png -------------------------------------------------------------------------------- /public/icons/favicon-128x128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/972784674t/quasar-manage/HEAD/public/icons/favicon-128x128.png -------------------------------------------------------------------------------- /.devTools/shell-chrome/devtools-background.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.devTools/shell-chrome/icons/128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/972784674t/quasar-manage/HEAD/.devTools/shell-chrome/icons/128.png -------------------------------------------------------------------------------- /.devTools/shell-chrome/icons/16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/972784674t/quasar-manage/HEAD/.devTools/shell-chrome/icons/16.png -------------------------------------------------------------------------------- /.devTools/shell-chrome/icons/48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/972784674t/quasar-manage/HEAD/.devTools/shell-chrome/icons/48.png -------------------------------------------------------------------------------- /src-electron/icons/linux-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/972784674t/quasar-manage/HEAD/src-electron/icons/linux-512x512.png -------------------------------------------------------------------------------- /.devTools/shell-electron/icons/128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/972784674t/quasar-manage/HEAD/.devTools/shell-electron/icons/128.png -------------------------------------------------------------------------------- /.devTools/shell-chrome/icons/128-beta.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/972784674t/quasar-manage/HEAD/.devTools/shell-chrome/icons/128-beta.png -------------------------------------------------------------------------------- /.devTools/shell-chrome/icons/128-gray.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/972784674t/quasar-manage/HEAD/.devTools/shell-chrome/icons/128-gray.png -------------------------------------------------------------------------------- /.devTools/shell-chrome/icons/128.nuxt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/972784674t/quasar-manage/HEAD/.devTools/shell-chrome/icons/128.nuxt.png -------------------------------------------------------------------------------- /.devTools/shell-chrome/icons/16-beta.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/972784674t/quasar-manage/HEAD/.devTools/shell-chrome/icons/16-beta.png -------------------------------------------------------------------------------- /.devTools/shell-chrome/icons/16-gray.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/972784674t/quasar-manage/HEAD/.devTools/shell-chrome/icons/16-gray.png -------------------------------------------------------------------------------- /.devTools/shell-chrome/icons/16.nuxt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/972784674t/quasar-manage/HEAD/.devTools/shell-chrome/icons/16.nuxt.png -------------------------------------------------------------------------------- /.devTools/shell-chrome/icons/48-beta.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/972784674t/quasar-manage/HEAD/.devTools/shell-chrome/icons/48-beta.png -------------------------------------------------------------------------------- /.devTools/shell-chrome/icons/48-gray.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/972784674t/quasar-manage/HEAD/.devTools/shell-chrome/icons/48-gray.png -------------------------------------------------------------------------------- /.devTools/shell-chrome/icons/48.nuxt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/972784674t/quasar-manage/HEAD/.devTools/shell-chrome/icons/48.nuxt.png -------------------------------------------------------------------------------- /.devTools/shell-electron/src/hook.js: -------------------------------------------------------------------------------- 1 | import { installHook } from '@back/hook' 2 | import { target } from '@utils/env' 3 | 4 | installHook(target) 5 | -------------------------------------------------------------------------------- /src/components/Layout/Layout.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 10 | -------------------------------------------------------------------------------- /src/store/state.js: -------------------------------------------------------------------------------- 1 | export default function () { 2 | return { 3 | role: '', 4 | routes: [], 5 | tagView: [], 6 | breadcrumbs: [], 7 | keepAliveList: [] 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | -------------------------------------------------------------------------------- /src/i18n/en-us/index.js: -------------------------------------------------------------------------------- 1 | // This is just an example, 2 | // so you can safely delete all default props below 3 | 4 | export default { 5 | failed: 'Action failed', 6 | success: 'Action was successful' 7 | } 8 | -------------------------------------------------------------------------------- /.devTools/shell-chrome/popups/not-found.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |

5 | Vue.js not detected 6 |

7 | -------------------------------------------------------------------------------- /.postcssrc.js: -------------------------------------------------------------------------------- 1 | // https://github.com/michael-ciniawsky/postcss-load-config 2 | 3 | module.exports = { 4 | plugins: [ 5 | // to edit target browsers: use "browserslist" field in package.json 6 | require('autoprefixer') 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /src/components/LoadingBar/LoadingBar.js: -------------------------------------------------------------------------------- 1 | import { LoadingBar } from 'quasar' 2 | 3 | LoadingBar.setDefaults({ 4 | color: 'my-loadingBar-color', 5 | size: '2.3px', 6 | position: 'top' 7 | }) 8 | 9 | export default LoadingBar 10 | -------------------------------------------------------------------------------- /.devTools/shell-chrome/popups/enabled.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |

5 | Vue.js is detected on this page.
6 | Open DevTools and look for the Vue panel. 7 |

8 | -------------------------------------------------------------------------------- /.devTools/shell-chrome/popups/enabled.nuxt.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |

5 | Nuxt.js + Vue.js is detected on this page.
6 | Open DevTools and look for the Vue panel. 7 |

8 | -------------------------------------------------------------------------------- /src/api/UserApi.js: -------------------------------------------------------------------------------- 1 | import _axios from '../axios/AxiosConfig' 2 | import Vue from 'vue' 3 | 4 | export function getUserRouter () { 5 | return _axios({ 6 | url: Vue.prototype.$PUBLIC_PATH + 'data/asyncRouterDemo', 7 | method: 'get', 8 | responseType: 'text' 9 | }) 10 | } 11 | -------------------------------------------------------------------------------- /src/components/Markdown/Markdown.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | 3 | import VMdEditor from '@kangc/v-md-editor' 4 | import '@kangc/v-md-editor/lib/style/base-editor.css' 5 | import vuepressTheme from '@kangc/v-md-editor/lib/theme/vuepress.js' 6 | 7 | VMdEditor.use(vuepressTheme) 8 | Vue.use(VMdEditor) 9 | -------------------------------------------------------------------------------- /src/assets/css/main.css: -------------------------------------------------------------------------------- 1 | .app-main { 2 | width: 100%; 3 | position: relative; 4 | } 5 | .echarts { 6 | width: 100% !important; 7 | height: 100% !important; 8 | } 9 | .main-content{ 10 | height: 100%; 11 | background-color: #fcfcff; 12 | } 13 | 14 | aside { 15 | top: 86px; 16 | } 17 | 18 | -------------------------------------------------------------------------------- /src/store/store-flag.d.ts: -------------------------------------------------------------------------------- 1 | // THIS FEATURE-FLAG FILE IS AUTOGENERATED, 2 | // REMOVAL OR CHANGES WILL CAUSE RELATED TYPES TO STOP WORKING 3 | import "quasar/dist/types/feature-flag"; 4 | 5 | declare module "quasar/dist/types/feature-flag" { 6 | interface QuasarFeatureFlags { 7 | store: true; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /.devTools/shell-chrome/popups/disabled.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |

5 | Vue.js is detected on this page.
6 | Devtools inspection is not available because it's in 7 | production mode or explicitly disabled by the author. 8 |

9 | -------------------------------------------------------------------------------- /src-electron/electron-flag.d.ts: -------------------------------------------------------------------------------- 1 | // THIS FEATURE-FLAG FILE IS AUTOGENERATED, 2 | // REMOVAL OR CHANGES WILL CAUSE RELATED TYPES TO STOP WORKING 3 | import "quasar/dist/types/feature-flag"; 4 | 5 | declare module "quasar/dist/types/feature-flag" { 6 | interface QuasarFeatureFlags { 7 | electron: true; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 6 | 11 | 12 | 17 | -------------------------------------------------------------------------------- /.devTools/shell-chrome/popups/disabled.nuxt.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |

5 | Nuxt.js + Vue.js is detected on this page.
6 | Devtools inspection is not available because it's in 7 | production mode or explicitly disabled by the author. 8 |

9 | -------------------------------------------------------------------------------- /.devTools/shell-electron/bin.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | const electron = require('electron') 3 | const spawn = require('cross-spawn') 4 | const argv = process.argv.slice(2) 5 | 6 | const result = spawn.sync( 7 | electron, 8 | [require.resolve('./app')].concat(argv), 9 | { stdio: 'ignore' } 10 | ) 11 | 12 | process.exit(result.status) 13 | -------------------------------------------------------------------------------- /src/store/getters.js: -------------------------------------------------------------------------------- 1 | const getters = { 2 | getRole: (state) => { return state.role }, 3 | getRoutes: (state) => { return state.routes }, 4 | getTagView: (state) => { return state.tagView }, 5 | getBreadcrumbs: (state) => { return state.breadcrumbs }, 6 | getKeepAliveList: (state) => { return state.keepAliveList } 7 | } 8 | 9 | export default getters 10 | -------------------------------------------------------------------------------- /src/boot/i18n.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import VueI18n from 'vue-i18n' 3 | import messages from 'src/i18n' 4 | 5 | Vue.use(VueI18n) 6 | 7 | const i18n = new VueI18n({ 8 | locale: 'en-us', 9 | fallbackLocale: 'en-us', 10 | messages 11 | }) 12 | 13 | export default ({ app }) => { 14 | // Set i18n instance on app 15 | app.i18n = i18n 16 | } 17 | 18 | export { i18n } 19 | -------------------------------------------------------------------------------- /src/components/BaseContent/ThumbStyle.js: -------------------------------------------------------------------------------- 1 | // 滚动条样式 2 | export const thumbStyle = { 3 | right: '5px', 4 | borderRadius: '5px', 5 | backgroundColor: '#616161', 6 | width: '5px' 7 | } 8 | 9 | export const thumbStyleOfMenu = { 10 | borderRadius: '5px', 11 | backgroundColor: 'rgba(144,147,153,0.9)', 12 | padding: '10px;', 13 | margin: '10px;', 14 | width: '3px' 15 | } 16 | -------------------------------------------------------------------------------- /src/components/ECharts/EChartsConfig.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | 3 | import ECharts from 'vue-echarts' 4 | 5 | // Manually introduce ECharts modules to reduce the packaging volume 6 | import 'echarts/lib/chart/bar' 7 | import 'echarts/lib/component/tooltip' 8 | import 'echarts/lib/chart/line' 9 | import 'echarts/lib/component/polar' 10 | import 'echarts/lib/chart/pie' 11 | 12 | Vue.component('v-chart', ECharts) 13 | -------------------------------------------------------------------------------- /src/css/app.css: -------------------------------------------------------------------------------- 1 | /* app global css */ 2 | html { 3 | height: 100%; 4 | box-sizing: border-box; 5 | color: #2c3e50; 6 | } 7 | body, 8 | #q-app{ 9 | height: 100%; 10 | margin: 0; 11 | padding: 0; 12 | -webkit-font-smoothing: antialiased; 13 | text-rendering: optimizeLegibility; 14 | overflow: hidden; 15 | font-family: 'Roboto', '-apple-system', 'Helvetica Neue', Helvetica, Arial, sans-serif !important; 16 | } 17 | -------------------------------------------------------------------------------- /src/components/Toolbar/ToolbarTitle.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 19 | -------------------------------------------------------------------------------- /.devTools/shell-chrome/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@vue-devtools/shell-chrome", 3 | "version": "0.0.0", 4 | "dependencies": { 5 | "@vue-devtools/app-backend": "^0.0.0", 6 | "@vue-devtools/app-frontend": "^0.0.0", 7 | "@vue-devtools/shared-utils": "^0.0.0" 8 | }, 9 | "devDependencies": { 10 | "@vue-devtools/build-tools": "^0.0.0", 11 | "webpack": "^4.19.0", 12 | "webpack-cli": "^3.3.12" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /.yarnrc: -------------------------------------------------------------------------------- 1 | registry "https://registry.npm.taobao.org" 2 | 3 | sass_binary_site "https://npm.taobao.org/mirrors/node-sass/" 4 | phantomjs_cdnurl "http://cnpmjs.org/downloads" 5 | electron_mirror "https://npm.taobao.org/mirrors/electron/" 6 | sqlite3_binary_host_mirror "https://foxgis.oss-cn-shanghai.aliyuncs.com/" 7 | profiler_binary_host_mirror "https://npm.taobao.org/mirrors/node-inspector/" 8 | chromedriver_cdnurl "https://cdn.npm.taobao.org/dist/chromedriver" 9 | -------------------------------------------------------------------------------- /.devTools/shell-chrome/popups/popup.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: Roboto, Avenir, Helvetica, Arial, sans-serif; 3 | font-size: 14px; 4 | font-weight: 400; 5 | line-height: 1.4; 6 | padding: 10px 12px 12px 12px; 7 | color: #2c3e50; 8 | } 9 | 10 | body, 11 | p { 12 | margin: 0; 13 | } 14 | 15 | p { 16 | min-width: 200px; 17 | max-width: 300px; 18 | } 19 | 20 | .short-paragraph { 21 | min-width: initial; 22 | white-space: nowrap; 23 | } 24 | -------------------------------------------------------------------------------- /src/pages/home/tableDetail.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 23 | -------------------------------------------------------------------------------- /.devTools/shell-chrome/devtools.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 15 | 16 | 17 |
18 |
19 |
20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/boot/main.js: -------------------------------------------------------------------------------- 1 | /** 2 | * main boot file 3 | */ 4 | // import _router from '../router/permission' 5 | import '../components/ECharts/EChartsConfig' 6 | import '../components/Markdown/Markdown' 7 | import '../quasar.manage.config' 8 | import '../axios/FetchData' 9 | import { handleBaiduStatistics } from 'src/utils/CloneUtils' 10 | 11 | // "async" is optional; 12 | // more info on params: https://quasar.dev/quasar-cli/boot-files 13 | export default async ({ app, router, Vue, publicPath }) => { 14 | handleBaiduStatistics() 15 | } 16 | -------------------------------------------------------------------------------- /.devTools/shell-electron/webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | const { createConfig } = require('@vue-devtools/build-tools') 3 | 4 | const target = { 5 | chrome: 52, 6 | firefox: 48, 7 | safari: 9, 8 | ie: 11 9 | } 10 | 11 | module.exports = createConfig({ 12 | entry: { 13 | devtools: './src/devtools.js', 14 | backend: './src/backend.js', 15 | hook: './src/hook.js' 16 | }, 17 | output: { 18 | path: path.join(__dirname, '/build'), 19 | publicPath: '/build/', 20 | filename: '[name].js' 21 | }, 22 | devtool: '#cheap-module-source-map' 23 | }, target) 24 | -------------------------------------------------------------------------------- /src/components/Skeleton/SkeletonDemo.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 21 | -------------------------------------------------------------------------------- /src/router/constantRoutes.js: -------------------------------------------------------------------------------- 1 | /** 2 | * constantRoutes : Users do not need to log in to access 3 | */ 4 | const constantRoutes = [ 5 | { 6 | path: '/logon', 7 | name: 'logon', 8 | meta: { 9 | title: '登录' 10 | }, 11 | component: () => import('pages/logon/logon.vue') 12 | }, 13 | { 14 | path: '/NoFound404', 15 | name: 'NoFound404', 16 | meta: { 17 | roles: ['admin', 'editor'], 18 | title: '404', 19 | icon: 'sentiment_dissatisfied', 20 | isHidden: true 21 | }, 22 | component: () => import('../components/404/NoFound404') 23 | } 24 | ] 25 | 26 | export default constantRoutes 27 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .thumbs.db 3 | node_modules 4 | 5 | # Quasar core related directories 6 | .quasar 7 | /dist 8 | 9 | # Cordova related directories and files 10 | /src-cordova/node_modules 11 | /src-cordova/platforms 12 | /src-cordova/plugins 13 | /src-cordova/www 14 | 15 | # Capacitor related directories and files 16 | /src-capacitor/www 17 | /src-capacitor/node_modules 18 | 19 | # BEX related directories and files 20 | /src-bex/www 21 | /src-bex/js/core 22 | 23 | # Log files 24 | npm-debug.log* 25 | yarn-debug.log* 26 | yarn-error.log* 27 | 28 | # Editor directories and files 29 | .idea 30 | .vscode 31 | *.suo 32 | *.ntvs* 33 | *.njsproj 34 | *.sln 35 | -------------------------------------------------------------------------------- /.devTools/shell-chrome/src/hook.js: -------------------------------------------------------------------------------- 1 | // This script is injected into every page. 2 | import { installHook } from '@back/hook' 3 | import { isFirefox } from '@utils/env' 4 | 5 | // inject the hook 6 | if (document instanceof HTMLDocument) { 7 | const source = ';(' + installHook.toString() + ')(window)' 8 | 9 | if (isFirefox) { 10 | // eslint-disable-next-line no-eval 11 | window.eval(source) // in Firefox, this evaluates on the content window 12 | } else { 13 | const script = document.createElement('script') 14 | script.textContent = source 15 | document.documentElement.appendChild(script) 16 | script.parentNode.removeChild(script) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/axios/FetchData.js: -------------------------------------------------------------------------------- 1 | import _axios from './AxiosConfig' 2 | import Vue from 'vue' 3 | 4 | /** 5 | * Custom general axios package class 6 | * @param query Request body 7 | * @returns {*} 8 | * @author cimo 9 | */ 10 | const fetchData = query => { 11 | return _axios({ 12 | url: query.url, 13 | method: query.method || 'POST', 14 | params: query.params, 15 | responseType: query.responseType || 'json', 16 | auth: query.auth || { username: localStorage.getItem('access_token') }, 17 | data: query.data || '', 18 | type: query.type // For custom request type, please see axios-config.js 19 | }) 20 | } 21 | 22 | Vue.prototype.$fetchData = fetchData 23 | -------------------------------------------------------------------------------- /src/components/Breadcrumbs/BreadcrumbsUtils.js: -------------------------------------------------------------------------------- 1 | import store from '../../store/index' 2 | import deepClone, { getFirst } from 'src/utils/CloneUtils' 3 | 4 | /** 5 | * 获取 matched 中的路径 title,并生成面包屑 6 | * 如果有 query 则取第一个参数附加在 title 上 7 | * @param matched to.matched[] 8 | * @param query 参数 9 | */ 10 | export function setBreadcrumbs (matched, query) { 11 | const temp = [] 12 | for (let i = 0; i < matched.length; i++) { 13 | temp.push(deepClone(matched[i].meta)) 14 | } 15 | const last = temp.length - 1 16 | // 如果有 query 则取第一个参数附加在 title 上 17 | Object.keys(query).length && (temp[last].title += ':' + getFirst(query)) 18 | store.commit('SET_BREADCRUMBS', temp) 19 | } 20 | -------------------------------------------------------------------------------- /.devTools/shell-chrome/webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | const { createConfig } = require('@vue-devtools/build-tools') 3 | 4 | module.exports = createConfig({ 5 | entry: { 6 | hook: './src/hook.js', 7 | devtools: './src/devtools.js', 8 | background: './src/background.js', 9 | 'devtools-background': './src/devtools-background.js', 10 | backend: './src/backend.js', 11 | proxy: './src/proxy.js', 12 | detector: './src/detector.js' 13 | }, 14 | output: { 15 | path: path.join(__dirname, 'build'), 16 | filename: '[name].js' 17 | }, 18 | devtool: process.env.NODE_ENV !== 'production' 19 | ? '#inline-source-map' 20 | : false 21 | }) 22 | -------------------------------------------------------------------------------- /jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "paths": { 5 | "src/*": [ 6 | "src/*" 7 | ], 8 | "app/*": [ 9 | "*" 10 | ], 11 | "components/*": [ 12 | "src/components/*" 13 | ], 14 | "layouts/*": [ 15 | "src/layouts/*" 16 | ], 17 | "pages/*": [ 18 | "src/pages/*" 19 | ], 20 | "assets/*": [ 21 | "src/assets/*" 22 | ], 23 | "boot/*": [ 24 | "src/boot/*" 25 | ], 26 | "vue$": [ 27 | "node_modules/vue/dist/vue.esm.js" 28 | ] 29 | } 30 | }, 31 | "exclude": [ 32 | "dist", 33 | ".quasar", 34 | "node_modules" 35 | ] 36 | } -------------------------------------------------------------------------------- /.devTools/shell-electron/index.js: -------------------------------------------------------------------------------- 1 | require('./build/hook.js') 2 | 3 | const target = typeof window !== 'undefined' 4 | ? window 5 | : typeof global !== 'undefined' 6 | ? global 7 | : {} 8 | 9 | module.exports = { 10 | connect: function (host, port, { io, showToast, app } = {}) { 11 | target.__VUE_DEVTOOLS_HOST__ = host 12 | target.__VUE_DEVTOOLS_PORT__ = port 13 | if (io) target.__VUE_DEVTOOLS_SOCKET__ = io 14 | if (showToast) target.__VUE_DEVTOOLS_TOAST__ = showToast 15 | if (app) target.__VUE_ROOT_INSTANCES__ = Array.isArray(app) ? app : [app] 16 | 17 | require('./build/backend.js') 18 | }, 19 | init: (Vue) => { 20 | const tools = target.__VUE_DEVTOOLS_GLOBAL_HOOK__ 21 | 22 | tools.emit('init', Vue) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/pages/components/markdown.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 35 | -------------------------------------------------------------------------------- /src/store/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Vuex from 'vuex' 3 | import state from './state' 4 | import getters from './getters' 5 | import mutations from 'src/store/mutations' 6 | import actions from './actions' 7 | import modules from './modules' 8 | // import example from './module-example' 9 | 10 | Vue.use(Vuex) 11 | 12 | /* 13 | * If not building with SSR mode, you can 14 | * directly export the Store instantiation; 15 | * 16 | * The function below can be async too; either use 17 | * async/await or return a Promise which resolves 18 | * with the Store instance. 19 | */ 20 | 21 | // export default function (/* { ssrContext } */) { 22 | const store = new Vuex.Store({ 23 | state, 24 | getters, 25 | mutations, 26 | actions, 27 | modules, 28 | // enable strict mode (adds overhead!) 29 | // for dev mode only 30 | strict: process.env.DEBUGGING 31 | }) 32 | 33 | export default store 34 | // } 35 | -------------------------------------------------------------------------------- /src/components/Menu/BaseMenu.vue: -------------------------------------------------------------------------------- 1 | 20 | 21 | 37 | -------------------------------------------------------------------------------- /.devTools/shell-electron/app.js: -------------------------------------------------------------------------------- 1 | // Start middleware server 2 | require('./server') 3 | 4 | const { app, BrowserWindow } = require('electron') 5 | const path = require('path') 6 | const url = require('url') 7 | 8 | let mainWindow = null 9 | 10 | function createWindow () { 11 | mainWindow = new BrowserWindow({ 12 | width: 800, 13 | height: 600, 14 | icon: path.join(__dirname, 'icons/128.png'), 15 | webPreferences: { 16 | nodeIntegration: true 17 | } 18 | }) 19 | 20 | mainWindow.loadURL(url.format({ 21 | pathname: path.join(__dirname, 'app.html'), 22 | protocol: 'file:', 23 | slashes: true 24 | })) 25 | 26 | mainWindow.on('closed', () => { 27 | mainWindow = null 28 | }) 29 | } 30 | 31 | app.on('ready', createWindow) 32 | 33 | app.on('window-all-closed', () => { 34 | if (process.platform !== 'darwin') { 35 | app.quit() 36 | } 37 | }) 38 | 39 | app.on('activate', () => { 40 | if (mainWindow === null) { 41 | createWindow() 42 | } 43 | }) 44 | -------------------------------------------------------------------------------- /src/quasar.manage.config.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | 3 | Vue.config.productionTip = false 4 | 5 | Vue.prototype.$PUBLIC_PATH = process.env.VUE_ROUTER_BASE 6 | 7 | // 浏览器 title 8 | Vue.prototype.$title = ' | Vue Quasar' 9 | 10 | // 侧边栏风格 11 | Vue.prototype.$SildeBar = 'hHh lpR fFf' // 风格二:lHh lpR fFf 12 | 13 | // axios 中请求基地址,如果需要请在 axios/axiosConfig.js 中打开,下面是跨域代理示例 14 | // Vue.prototype.$baseURL = process.env.NODE_ENV === 'development' ? '/api/' : '生产环境 API' 15 | Vue.prototype.$baseURL = '' 16 | 17 | // 请求超时时间 18 | Vue.prototype.$timeOut = 8000 19 | 20 | // 组件最大缓存数 21 | Vue.prototype.$Max_KeepAlive = 10 22 | 23 | // 侧边栏底部文字 24 | Vue.prototype.$buttonList = [ 25 | { text: 'Quasar', URL: 'http://www.quasarchs.com/' }, 26 | { text: 'Github', URL: 'https://github.com/972784674t/vue-quasar-manage' }, 27 | { text: 'Gitee', URL: 'https://gitee.com/incimo/vue-quasar-manage' }, 28 | { text: 'GreaterWMS', URL: 'https://github.com/Singosgu/GreaterWMS' }, 29 | { text: '关于作者', URL: '/cimo' } 30 | ] 31 | -------------------------------------------------------------------------------- /src/index.template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | <%= productName %> 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 | 22 | 23 | -------------------------------------------------------------------------------- /.devTools/shell-electron/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@vue/devtools", 3 | "version": "5.3.3", 4 | "description": "StandAlone vue-devtools", 5 | "repository": { 6 | "url": "https://github.com/vuejs/vue-devtools.git", 7 | "type": "git" 8 | }, 9 | "bin": { 10 | "vue-devtools": "./bin.js" 11 | }, 12 | "main": "index.js", 13 | "types": "types/index.d.ts", 14 | "scripts": { 15 | "start": "node bin.js", 16 | "dev": "webpack --watch --hide-modules", 17 | "build": "webpack", 18 | "prepublishOnly": "npm run build" 19 | }, 20 | "author": "", 21 | "license": "MIT", 22 | "publishConfig": { 23 | "access": "public" 24 | }, 25 | "dependencies": { 26 | "cross-spawn": "^5.1.0", 27 | "electron": "^7.0.0", 28 | "express": "^4.16.2", 29 | "ip": "^1.1.5", 30 | "socket.io": "^2.0.4" 31 | }, 32 | "devDependencies": { 33 | "@vue-devtools/app-backend": "^0.0.0", 34 | "@vue-devtools/app-frontend": "^0.0.0", 35 | "@vue-devtools/build-tools": "^0.0.0", 36 | "@vue-devtools/shared-utils": "^0.0.0", 37 | "webpack": "^4.19.0", 38 | "webpack-cli": "^3.1.0" 39 | } 40 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Cimo 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/components/404/NoFound404.vue: -------------------------------------------------------------------------------- 1 | 18 | 19 | 32 | 44 | -------------------------------------------------------------------------------- /src/pages/router/asyncRouterImpl.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 44 | -------------------------------------------------------------------------------- /src/pages/router/myMenu.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 44 | -------------------------------------------------------------------------------- /src/assets/css/cimo.css: -------------------------------------------------------------------------------- 1 | .cimo-shadow { 2 | box-shadow: rgba(0, 0, 0, 0.1) 0px 2px 12px 0px !important; 3 | transition: All 0.2s ease-in-out; 4 | } 5 | .cimo-shadow:hover{ 6 | box-shadow: rgba(0, 0, 0, 0.1) 0px 2px 13px 3px !important; 7 | } 8 | .base-card-shadow{ 9 | box-shadow: rgba(0, 0, 0, 0.1) 0px 2px 12px 0px; 10 | border-radius: 4px; 11 | } 12 | .base-markdown-content{ 13 | padding: 0px 10px 0px 10px; 14 | max-width: 760px; 15 | margin: 0 auto; 16 | color: #2c3e50; 17 | font-size: 16px; 18 | font-family: -apple-system, BlinkMacSystemFont, Segoe UI Emoji, Roboto, Oxygen, Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; 19 | word-wrap: break-word; 20 | -webkit-font-smoothing: antialiased; 21 | } 22 | .bg-my-loadingBar-color{ 23 | background-image: linear-gradient(to right, #56ccf2, #2f80ed, #eeeeee) !important; 24 | background-size: 400% !important; 25 | animation: loadingBar-animation 3s infinite; 26 | } 27 | @keyframes loadingBar-animation { 28 | 0% { 29 | background-position: 0 0; 30 | } 31 | 100% { 32 | background-position: -100% 0; 33 | } 34 | } 35 | 36 | aside { 37 | top: 86px !important; 38 | } 39 | 40 | -------------------------------------------------------------------------------- /src/pages/components/scrollDemo.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 44 | -------------------------------------------------------------------------------- /src/pages/components/tagViewDemo.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 44 | -------------------------------------------------------------------------------- /src/pages/router/gettingStarted.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 44 | -------------------------------------------------------------------------------- /src/pages/axios/axios.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 48 | -------------------------------------------------------------------------------- /src/pages/components/keepaliveDoc.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 44 | -------------------------------------------------------------------------------- /src/pages/components/loadingBar.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 44 | -------------------------------------------------------------------------------- /.devTools/shell-electron/server.js: -------------------------------------------------------------------------------- 1 | const app = require('express')() 2 | const http = require('http').Server(app) 3 | const io = require('socket.io')(http) 4 | const path = require('path') 5 | const fs = require('fs') 6 | 7 | const port = process.env.PORT || 8098 8 | 9 | app.get('/', function (req, res) { 10 | const hookContent = fs.readFileSync(path.join(__dirname, '/build/hook.js'), 'utf8') 11 | const backendContent = fs.readFileSync(path.join(__dirname, '/build/backend.js'), 'utf8') 12 | res.send([hookContent, backendContent].join('\n')) 13 | }) 14 | 15 | // Middleman 16 | io.on('connection', function (socket) { 17 | // Disconnect any previously connected apps 18 | socket.broadcast.emit('vue-devtools-disconnect-backend') 19 | 20 | socket.on('vue-devtools-init', () => { 21 | socket.broadcast.emit('vue-devtools-init') 22 | }) 23 | 24 | socket.on('disconnect', (reason) => { 25 | if (reason.indexOf('client')) { 26 | socket.broadcast.emit('vue-devtools-disconnect-devtools') 27 | } 28 | }) 29 | 30 | socket.on('vue-message', data => { 31 | socket.broadcast.emit('vue-message', data) 32 | }) 33 | }) 34 | 35 | http.listen(port, '0.0.0.0', () => { 36 | console.log('listening on 0.0.0.0:' + port) 37 | }) 38 | -------------------------------------------------------------------------------- /src/pages/router/routerConfig.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 44 | -------------------------------------------------------------------------------- /src/utils/CloneUtils.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Deep clone 3 | * @param obj 4 | * @returns {[]|{}} 5 | */ 6 | function deepClone (obj) { 7 | if (obj === null) { 8 | return 9 | } 10 | const newObj = obj.push ? [] : {} // 如果obj有push方法则 定义newObj为数组,否则为对象。 11 | for (const attr in obj) { 12 | if (typeof obj[attr] === 'object') { 13 | newObj[attr] = deepClone(obj[attr]) 14 | } else { 15 | newObj[attr] = obj[attr] 16 | } 17 | } 18 | return newObj 19 | } 20 | 21 | /** 22 | * Get the first element of the object 23 | * @param obj 24 | * @returns {*} 25 | */ 26 | export function getFirst (obj) { 27 | for (const key in obj) { 28 | return obj[key] 29 | } 30 | } 31 | 32 | /** 33 | * 处理百度统计 Processing Baidu statistics 34 | */ 35 | export function handleBaiduStatistics () { 36 | // eslint-disable-next-line no-use-before-define 37 | var _hmt = _hmt || [] 38 | window._hmt = _hmt; // Mount _hmt under the window 39 | (function () { 40 | var hm = document.createElement('script') 41 | hm.src = 'https://hm.baidu.com/hm.js?a58d33108bfd0357ba78d883f1149708' 42 | var s = document.getElementsByTagName('script')[0] 43 | s.parentNode.insertBefore(hm, s) 44 | })() 45 | } 46 | 47 | export default deepClone 48 | -------------------------------------------------------------------------------- /src/pages/components/breadCrumbsDemo.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 44 | -------------------------------------------------------------------------------- /.devTools/shell-chrome/src/proxy.js: -------------------------------------------------------------------------------- 1 | // This is a content-script that is injected only when the devtools are 2 | // activated. Because it is not injected using eval, it has full privilege 3 | // to the chrome runtime API. It serves as a proxy between the injected 4 | // backend and the Vue devtools panel. 5 | 6 | const port = chrome.runtime.connect({ 7 | name: 'content-script' 8 | }) 9 | 10 | port.onMessage.addListener(sendMessageToBackend) 11 | window.addEventListener('message', sendMessageToDevtools) 12 | port.onDisconnect.addListener(handleDisconnect) 13 | 14 | sendMessageToBackend('init') 15 | 16 | function sendMessageToBackend (payload) { 17 | window.postMessage({ 18 | source: 'vue-devtools-proxy', 19 | payload: payload 20 | }, '*') 21 | } 22 | 23 | function sendMessageToDevtools (e) { 24 | if (e.data && e.data.source === 'vue-devtools-backend') { 25 | port.postMessage(e.data.payload) 26 | } else if (e.data && e.data.source === 'vue-devtools-backend-injection') { 27 | if (e.data.payload === 'listening') { 28 | sendMessageToBackend('init') 29 | } 30 | } 31 | } 32 | 33 | function handleDisconnect () { 34 | window.removeEventListener('message', sendMessageToDevtools) 35 | sendMessageToBackend('shutdown') 36 | } 37 | -------------------------------------------------------------------------------- /src/pages/optimization/VolumeOptimization.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 44 | -------------------------------------------------------------------------------- /src/pages/optimization/renderOptimization.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 43 | -------------------------------------------------------------------------------- /src/components/Breadcrumbs/Breadcrumbs.vue: -------------------------------------------------------------------------------- 1 | 21 | 22 | 45 | -------------------------------------------------------------------------------- /src/pages/components/menu3.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 54 | -------------------------------------------------------------------------------- /.devTools/shell-electron/src/devtools.js: -------------------------------------------------------------------------------- 1 | import io from 'socket.io-client' 2 | import { initDevTools } from '@front' 3 | import Bridge from '@utils/bridge' 4 | 5 | const port = window.process.env.PORT || 8098 6 | const socket = io('http://localhost:' + port) 7 | const $ = document.querySelector.bind(document) 8 | const $intro = $('#intro') 9 | 10 | let reload = null 11 | let introTimer 12 | 13 | socket.on('vue-devtools-disconnect-devtools', () => { 14 | introTimer = setTimeout(() => { 15 | $intro.classList.remove('hidden') 16 | }, 2000) 17 | }) 18 | 19 | socket.on('vue-devtools-init', () => { 20 | clearTimeout(introTimer) 21 | $intro.classList.add('hidden') 22 | 23 | // Reset attached listeners 24 | socket.off('vue-message') 25 | 26 | // If new page is opened reload devtools 27 | if (reload) return reload() 28 | 29 | initDevTools({ 30 | connect (callback) { 31 | const wall = { 32 | listen (fn) { 33 | socket.on('vue-message', data => fn(data)) 34 | }, 35 | send (data) { 36 | console.log('devtools -> backend', data) 37 | socket.emit('vue-message', data) 38 | } 39 | } 40 | const bridge = new Bridge(wall) 41 | 42 | callback(bridge) 43 | }, 44 | onReload (fn) { 45 | reload = fn 46 | } 47 | }) 48 | }) 49 | -------------------------------------------------------------------------------- /src/assets/css/transition.css: -------------------------------------------------------------------------------- 1 | /* Global transition animation css */ 2 | 3 | .fade-enter-active, 4 | .fade-leave-active { 5 | transition: opacity 0.28s; 6 | } 7 | 8 | .fade-enter, 9 | .fade-leave-active { 10 | opacity: 0; 11 | } 12 | 13 | .fade-transform-leave-active, 14 | .fade-transform-enter-active { 15 | transition: all .5s; 16 | } 17 | 18 | .fade-transform-enter { 19 | opacity: 0; 20 | transform: translateX(-30px); 21 | } 22 | 23 | .fade-transform-leave-to { 24 | opacity: 0; 25 | transform: translateX(30px); 26 | } 27 | 28 | /* breadcrumb transition */ 29 | 30 | .breadcrumb-enter { 31 | opacity: 0; 32 | transform: translateX(30px); 33 | } 34 | 35 | .breadcrumb-enter-active { 36 | transition: all .5s; 37 | } 38 | 39 | .breadcrumb-enter-to { 40 | opacity: 1; 41 | } 42 | 43 | .breadcrumb-leave { 44 | opacity: 1; 45 | transform: translateX(0px); 46 | } 47 | 48 | .breadcrumb-move { 49 | transition: all .5s; 50 | } 51 | 52 | .breadcrumb-leave-active { 53 | transition: all .5s; 54 | position: absolute; 55 | width: 500px; 56 | } 57 | 58 | .breadcrumb-leave-to { 59 | opacity: 0; 60 | transform: translateX(65px); 61 | } 62 | 63 | /* tagView transition */ 64 | 65 | .tagView-enter-active { 66 | transition: opacity .5s; 67 | } 68 | .tagView-enter, .tagView-leave-to { 69 | opacity: 0; 70 | } 71 | -------------------------------------------------------------------------------- /public/data/startData.md: -------------------------------------------------------------------------------- 1 | ## 快速起步 2 | 项目基于 [quasar-cli](http://www.quasarchs.com/start/quasar-cli) 3 | 4 | 目录结构 5 | ```sh 6 | src 7 | |-assets # 静态文件 8 | |-axios # 自定义 axois 9 | |-components # 全局组件 10 | |-layouts # 主布局文件 11 | |-router # 路由配置 12 | |-store # 全局状态 13 | |-utils # 工具类 14 | |-pages # 视图组件 15 | |-css # 全局 css 16 | |-boot # 自定义启动文件 17 | |-permission.js # 鉴权文件 18 | |-manage.config.js # 项目配置文件 19 | src-electron # electron 配置文件 20 | quasar.conf.js # quasar 配置文件 21 | ``` 22 | 23 | 1、根据需要对```manage.config.js```中的项目配置进行修改 24 | 25 | 2、弄清楚路由守卫如何工作及鉴权 26 | :::tip 27 | 个人认为代码是最好的老师,看代码比看图理解的快 ヽ(ー_ー)ノ [代码地址](https://github.com/972784674t/quasar-manage/blob/master/src/boot/permission.js) 28 | 相信不同的项目有不同逻辑操作,所以并没有把权限判断代码写得太详细 29 | ::: 30 | 31 | ![在这里插入图片描述](https://img-blog.csdnimg.cn/20201119170329453.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQxOTEyMzk4,size_16,color_FFFFFF,t_70#pic_center) 32 | 3、所有视图组件都请使用``````作为根元素,因为在``````做了缓存处理、滚动位置记录以及不同屏幕尺寸的适配,而且能使页面的滚动区域保持在特定的范围内 33 | 34 | :::tip 35 | 当然,越是精确的组件复用性越差,如果能根据``````(说明文档在:[滚动区域](#/component/scrollDemo)),封装一个更适合自己的组件,就再好不过了。 36 | ::: 37 | 38 | 做了这些事情基本可以愉快的使用项目了,现在在看的这个项目集展示和说明文档为一身,所以最好使用模板项目来进行开发哦 39 | 40 | 如果想深入了解可以查看后续的说明文档 41 | -------------------------------------------------------------------------------- /.devTools/shell-chrome/build/proxy.js: -------------------------------------------------------------------------------- 1 | (function(e){var t={};function n(o){if(t[o])return t[o].exports;var r=t[o]={i:o,l:!1,exports:{}};return e[o].call(r.exports,r,r.exports,n),r.l=!0,r.exports}n.m=e,n.c=t,n.d=function(e,t,o){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:o})},n.r=function(e){"undefined"!==typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"===typeof e&&e&&e.__esModule)return e;var o=Object.create(null);if(n.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)n.d(o,r,function(t){return e[t]}.bind(null,r));return o},n.n=function(e){var t=e&&e.__esModule?function(){return e["default"]}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=262)})({262:function(e,t){var n=chrome.runtime.connect({name:"content-script"});function o(e){window.postMessage({source:"vue-devtools-proxy",payload:e},"*")}function r(e){e.data&&"vue-devtools-backend"===e.data.source?n.postMessage(e.data.payload):e.data&&"vue-devtools-backend-injection"===e.data.source&&"listening"===e.data.payload&&o("init")}function a(){window.removeEventListener("message",r),o("shutdown")}n.onMessage.addListener(o),window.addEventListener("message",r),n.onDisconnect.addListener(a),o("init")}}); -------------------------------------------------------------------------------- /src-electron/main-process/electron-main.dev.js: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is used specifically and only for development. It installs 3 | * `electron-debug` & `vue-devtools`. There shouldn't be any need to 4 | * modify this file, but it can be used to extend your development 5 | * environment. 6 | */ 7 | 8 | import electronDebug from 'electron-debug' 9 | import installExtension, { VUEJS_DEVTOOLS } from 'electron-devtools-installer' 10 | import { app, BrowserWindow } from 'electron' 11 | 12 | app.whenReady().then(() => { 13 | // allow for a small delay for mainWindow to be created 14 | setTimeout(() => { 15 | // Install `electron-debug` with `devtron` 16 | electronDebug({ showDevTools: false }) 17 | 18 | // Install vuejs devtools 19 | installExtension(VUEJS_DEVTOOLS) 20 | .then(name => { 21 | console.log(`Added Extension: ${name}`) 22 | // get main window 23 | const win = BrowserWindow.getFocusedWindow() 24 | if (win) { 25 | win.webContents.on('did-frame-finish-load', () => { 26 | win.webContents.once('devtools-opened', () => { 27 | win.webContents.focus() 28 | }) 29 | // open electron debug 30 | console.log('Opening dev tools') 31 | win.webContents.openDevTools() 32 | }) 33 | } 34 | }) 35 | .catch(err => { 36 | console.log('An error occurred: ', err) 37 | }) 38 | }, 250) 39 | }) 40 | 41 | import './electron-main' 42 | -------------------------------------------------------------------------------- /.devTools/shell-chrome/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Vue.js devtools", 3 | "version": "5.3.3", 4 | "version_name": "5.3.3", 5 | "description": "Chrome and Firefox DevTools extension for debugging Vue.js applications.", 6 | "manifest_version": 2, 7 | "icons": { 8 | "16": "icons/16.png", 9 | "48": "icons/48.png", 10 | "128": "icons/128.png" 11 | }, 12 | "browser_action": { 13 | "default_icon": { 14 | "16": "icons/16-gray.png", 15 | "48": "icons/48-gray.png", 16 | "128": "icons/128-gray.png" 17 | }, 18 | "default_title": "Vue Devtools", 19 | "default_popup": "popups/not-found.html" 20 | }, 21 | "web_accessible_resources": [ 22 | "devtools.html", 23 | "devtools-background.html", 24 | "build/backend.js" 25 | ], 26 | "devtools_page": "devtools-background.html", 27 | "background": { 28 | "scripts": [ 29 | "build/background.js" 30 | ], 31 | "persistent": false 32 | }, 33 | "permissions": [ 34 | "http://*/*", 35 | "https://*/*", 36 | "file:///*", 37 | "contextMenus", 38 | "storage" 39 | ], 40 | "content_scripts": [ 41 | { 42 | "matches": [ 43 | "" 44 | ], 45 | "js": [ 46 | "build/hook.js" 47 | ], 48 | "run_at": "document_start" 49 | }, 50 | { 51 | "matches": [ 52 | "" 53 | ], 54 | "js": [ 55 | "build/detector.js" 56 | ], 57 | "run_at": "document_idle" 58 | } 59 | ] 60 | } -------------------------------------------------------------------------------- /public/data/loadingBarData.md: -------------------------------------------------------------------------------- 1 | ## LoadingBar 加载栏 2 | 3 | [[toc]] 4 | 5 | 加载栏配置在```/components/loadingBar``` 6 | ```js 7 | import { LoadingBar } from 'quasar' 8 | 9 | LoadingBar.setDefaults({ 10 | color: 'blue', 11 | size: '2.3px', 12 | position: 'top' 13 | }) 14 | 15 | export default LoadingBar 16 | ``` 17 | 之后在路由守卫中使用它 18 | ```js 19 | import LoadingBar from '../components/loadingBar/loadingBar' 20 | 21 | router.beforeEach((to, from, next) => { 22 | LoadingBar.start() 23 | ...... 24 | } 25 | 26 | router.afterEach(() => { 27 | LoadingBar.stop() 28 | }) 29 | ``` 30 | ### 如何自定义颜色 31 | 在```css```中添加 32 | ```css 33 | /* 必须以 bg- 开头 */ 34 | .bg-my-loadingBar-color{ 35 | background: red 36 | } 37 | ``` 38 | 在```LoadingBar.js```中使用 39 | ```js 40 | import { LoadingBar } from 'quasar' 41 | 42 | LoadingBar.setDefaults({ 43 | // 注意:loadingBar 在装载颜色时,会在类名前面自动加上'bg-', 44 | // 因此我们只需要填写 'my-loadingBar-color' 即可 45 | color: 'my-loadingBar-color', 46 | size: '2.3px', 47 | position: 'top' 48 | }) 49 | 50 | export default LoadingBar 51 | ``` 52 | ### 为加载栏添加动画效果 53 | 在```css```中 54 | ```css 55 | .bg-my-loadingBar-color{ 56 | background-image: linear-gradient(to right, #56ccf2, #2f80ed, #eeeeee) !important; 57 | background-size: 400% !important; 58 | animation: loadingBar_animation 3s infinite; 59 | } 60 | 61 | @keyframes loadingBar_animation { 62 | 0% { 63 | background-position: 0 0; 64 | } 65 | 100% { 66 | background-position: -100% 0; 67 | } 68 | } 69 | ``` 70 | -------------------------------------------------------------------------------- /.devTools/shell-chrome/src/backend.js: -------------------------------------------------------------------------------- 1 | // this is injected to the app page when the panel is activated. 2 | 3 | import { initBackend } from '@back' 4 | import Bridge from '@utils/bridge' 5 | 6 | window.addEventListener('message', handshake) 7 | 8 | function sendListening () { 9 | window.postMessage({ 10 | source: 'vue-devtools-backend-injection', 11 | payload: 'listening' 12 | }, '*') 13 | } 14 | sendListening() 15 | 16 | function handshake (e) { 17 | if (e.data.source === 'vue-devtools-proxy' && e.data.payload === 'init') { 18 | window.removeEventListener('message', handshake) 19 | 20 | let listeners = [] 21 | const bridge = new Bridge({ 22 | listen (fn) { 23 | const listener = evt => { 24 | if (evt.data.source === 'vue-devtools-proxy' && evt.data.payload) { 25 | fn(evt.data.payload) 26 | } 27 | } 28 | window.addEventListener('message', listener) 29 | listeners.push(listener) 30 | }, 31 | send (data) { 32 | // if (process.env.NODE_ENV !== 'production') { 33 | // console.log('[chrome] backend -> devtools', data) 34 | // } 35 | window.postMessage({ 36 | source: 'vue-devtools-backend', 37 | payload: data 38 | }, '*') 39 | } 40 | }) 41 | 42 | bridge.on('shutdown', () => { 43 | listeners.forEach(l => { 44 | window.removeEventListener('message', l) 45 | }) 46 | listeners = [] 47 | }) 48 | 49 | initBackend(bridge) 50 | } else { 51 | sendListening() 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/assets/js/echarts-3.js: -------------------------------------------------------------------------------- 1 | export const income = { 2 | xAxis: { 3 | type: 'category', 4 | show: false 5 | }, 6 | yAxis: { 7 | type: 'value', 8 | show: false 9 | }, 10 | series: [{ 11 | data: [10, 50, 36, 85, 98, 72, 79, 88, 80], 12 | type: 'line', 13 | smooth: true, 14 | show: false, 15 | symbol: 'none', 16 | animationDuration: 1000, 17 | itemStyle: { 18 | normal: { 19 | lineStyle: { 20 | color: '#ffffff' 21 | } 22 | 23 | } 24 | } 25 | }] 26 | } 27 | 28 | export const expense = { 29 | xAxis: { 30 | type: 'category', 31 | show: false 32 | }, 33 | yAxis: { 34 | type: 'value', 35 | show: false 36 | }, 37 | series: [{ 38 | data: [50, 42, 36, 78, 56, 72, 20, 15, 35], 39 | type: 'line', 40 | smooth: true, 41 | show: false, 42 | symbol: 'none', 43 | animationDuration: 1000, 44 | itemStyle: { 45 | normal: { 46 | lineStyle: { 47 | color: '#ffffff' 48 | } 49 | 50 | } 51 | } 52 | }] 53 | } 54 | 55 | export const total = { 56 | xAxis: { 57 | type: 'category', 58 | show: false 59 | }, 60 | yAxis: { 61 | type: 'value', 62 | show: false 63 | }, 64 | series: [{ 65 | data: [30, 45, 64, 78, 79, 80, 75, 70, 90], 66 | type: 'line', 67 | smooth: true, 68 | show: false, 69 | symbol: 'none', 70 | animationDuration: 1000, 71 | itemStyle: { 72 | normal: { 73 | lineStyle: { 74 | color: '#ffffff' 75 | } 76 | 77 | } 78 | } 79 | }] 80 | } 81 | -------------------------------------------------------------------------------- /src/components/Menu/BottomLink.vue: -------------------------------------------------------------------------------- 1 | 36 | 37 | 48 | 59 | -------------------------------------------------------------------------------- /src/components/LottieWebCimo/LottieWebCimo.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 67 | -------------------------------------------------------------------------------- /.devTools/shell-electron/src/backend.js: -------------------------------------------------------------------------------- 1 | import io from 'socket.io-client' 2 | import { initBackend } from '@back' 3 | import Bridge from '@utils/bridge' 4 | import { installToast } from '@back/toast' 5 | import { target } from '@utils/env' 6 | 7 | const host = target.__VUE_DEVTOOLS_HOST__ || 'http://localhost' 8 | const port = target.__VUE_DEVTOOLS_PORT__ !== undefined ? target.__VUE_DEVTOOLS_PORT__ : 8098 9 | const fullHost = port ? host + ':' + port : host 10 | const createSocket = target.__VUE_DEVTOOLS_SOCKET__ || io 11 | const socket = createSocket(fullHost) 12 | 13 | const connectedMessage = () => { 14 | if (target.__VUE_DEVTOOLS_TOAST__) { 15 | target.__VUE_DEVTOOLS_TOAST__('Remote Devtools Connected', 'normal') 16 | } 17 | } 18 | 19 | const disconnectedMessage = () => { 20 | if (target.__VUE_DEVTOOLS_TOAST__) { 21 | target.__VUE_DEVTOOLS_TOAST__('Remote Devtools Disconnected', 'error') 22 | } 23 | } 24 | 25 | socket.on('connect', () => { 26 | connectedMessage() 27 | initBackend(bridge) 28 | socket.emit('vue-devtools-init') 29 | }) 30 | 31 | // Global disconnect handler. Fires in two cases: 32 | // - after calling above socket.disconnect() 33 | // - once devtools is closed (that's why we need socket.disconnect() here too, to prevent further polling) 34 | socket.on('disconnect', (reason) => { 35 | socket.disconnect() 36 | disconnectedMessage() 37 | }) 38 | 39 | // Disconnect socket once other client is connected 40 | socket.on('vue-devtools-disconnect-backend', () => { 41 | socket.disconnect() 42 | }) 43 | 44 | const bridge = new Bridge({ 45 | listen (fn) { 46 | socket.on('vue-message', data => fn(data)) 47 | }, 48 | send (data) { 49 | socket.emit('vue-message', data) 50 | } 51 | }) 52 | 53 | bridge.on('shutdown', () => { 54 | socket.disconnect() 55 | disconnectedMessage() 56 | }) 57 | 58 | installToast(target) 59 | -------------------------------------------------------------------------------- /src/pages/components/json.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 72 | -------------------------------------------------------------------------------- /src-electron/main-process/electron-main.js: -------------------------------------------------------------------------------- 1 | import { app, BrowserWindow, nativeTheme, session } from 'electron' 2 | import path from 'path' 3 | 4 | try { 5 | if (process.platform === 'win32' && nativeTheme.shouldUseDarkColors === true) { 6 | require('fs').unlinkSync(require('path').join(app.getPath('userData'), 'DevTools Extensions')) 7 | } 8 | } catch (_) { } 9 | 10 | /** 11 | * Set `__statics` path to static files in production; 12 | * The reason we are setting it here is that the path needs to be evaluated at runtime 13 | */ 14 | if (process.env.PROD) { 15 | global.__statics = __dirname 16 | } 17 | 18 | let mainWindow 19 | 20 | function createWindow () { 21 | /** 22 | * Initial window options 23 | */ 24 | mainWindow = new BrowserWindow({ 25 | width: 500, 26 | height: 490, 27 | useContentSize: true, 28 | frame: false, 29 | webPreferences: { 30 | // Change from /quasar.conf.js > electron > nodeIntegration; 31 | // More info: https://quasar.dev/quasar-cli/developing-electron-apps/node-integration 32 | nodeIntegration: process.env.QUASAR_NODE_INTEGRATION, 33 | nodeIntegrationInWorker: process.env.QUASAR_NODE_INTEGRATION 34 | 35 | // More info: /quasar-cli/developing-electron-apps/electron-preload-script 36 | // preload: path.resolve(__dirname, 'electron-preload.js') 37 | } 38 | }) 39 | 40 | mainWindow.loadURL(process.env.APP_URL) 41 | 42 | mainWindow.on('closed', () => { 43 | mainWindow = null 44 | }) 45 | 46 | // devTools 47 | // session.defaultSession.loadExtension( 48 | // path.resolve(__dirname, '../../.devTools/shell-chrome') // 这个是刚刚build好的插件目录 49 | // ) 50 | } 51 | 52 | app.on('ready', createWindow) 53 | 54 | app.on('window-all-closed', () => { 55 | if (process.platform !== 'darwin') { 56 | app.quit() 57 | } 58 | }) 59 | 60 | app.on('activate', () => { 61 | if (mainWindow === null) { 62 | createWindow() 63 | } 64 | }) 65 | -------------------------------------------------------------------------------- /.devTools/shell-chrome/src/detector.js: -------------------------------------------------------------------------------- 1 | import { installToast } from '@back/toast' 2 | import { isFirefox } from '@utils/env' 3 | 4 | window.addEventListener('message', e => { 5 | if (e.source === window && e.data.vueDetected) { 6 | chrome.runtime.sendMessage(e.data) 7 | } 8 | }) 9 | 10 | function detect (win) { 11 | setTimeout(() => { 12 | // Method 1: Check Nuxt.js 13 | const nuxtDetected = Boolean(window.__NUXT__ || window.$nuxt) 14 | 15 | if (nuxtDetected) { 16 | let Vue 17 | 18 | if (window.$nuxt) { 19 | Vue = window.$nuxt.$root.constructor 20 | } 21 | 22 | win.postMessage({ 23 | devtoolsEnabled: Vue && Vue.config.devtools, 24 | vueDetected: true, 25 | nuxtDetected: true 26 | }, '*') 27 | 28 | return 29 | } 30 | 31 | // Method 2: Scan all elements inside document 32 | const all = document.querySelectorAll('*') 33 | let el 34 | for (let i = 0; i < all.length; i++) { 35 | if (all[i].__vue__) { 36 | el = all[i] 37 | break 38 | } 39 | } 40 | if (el) { 41 | let Vue = Object.getPrototypeOf(el.__vue__).constructor 42 | while (Vue.super) { 43 | Vue = Vue.super 44 | } 45 | win.postMessage({ 46 | devtoolsEnabled: Vue.config.devtools, 47 | vueDetected: true 48 | }, '*') 49 | } 50 | }, 100) 51 | } 52 | 53 | // inject the hook 54 | if (document instanceof HTMLDocument) { 55 | installScript(detect) 56 | installScript(installToast) 57 | } 58 | 59 | function installScript (fn) { 60 | const source = ';(' + fn.toString() + ')(window)' 61 | 62 | if (isFirefox) { 63 | // eslint-disable-next-line no-eval 64 | window.eval(source) // in Firefox, this evaluates on the content window 65 | } else { 66 | const script = document.createElement('script') 67 | script.textContent = source 68 | document.documentElement.appendChild(script) 69 | script.parentNode.removeChild(script) 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "quasar-manage", 3 | "version": "0.0.1", 4 | "description": "A Quasar Framework app", 5 | "productName": "Quasar Manage", 6 | "author": "cimo <972784674@qq.com>", 7 | "private": true, 8 | "scripts": { 9 | "dev:spa": "quasar dev", 10 | "dev:electron": "quasar dev -m electron", 11 | "build:spa": "quasar build", 12 | "build:electron": "quasar build -m electron", 13 | "clean": "quasar clean", 14 | "lint": "eslint --ext .js,.vue ./" 15 | }, 16 | "dependencies": { 17 | "@quasar/extras": "^1.0.0", 18 | "axios": "^0.18.1", 19 | "core-js": "^3.6.5", 20 | "quasar": "^1.0.0", 21 | "vue-i18n": "^8.0.0" 22 | }, 23 | "devDependencies": { 24 | "@kangc/v-md-editor": "1.4.10", 25 | "@quasar/app": "^2.0.0", 26 | "babel-eslint": "^10.0.1", 27 | "devtron": "^1.4.0", 28 | "echarts": "^4.9.0", 29 | "electron": "^9.0.0", 30 | "electron-debug": "^3.0.1", 31 | "electron-devtools-installer": "^3.0.0", 32 | "electron-packager": "^14.1.1", 33 | "eslint": "^6.8.0", 34 | "eslint-config-standard": "^14.1.0", 35 | "eslint-loader": "^3.0.3", 36 | "eslint-plugin-import": "^2.14.0", 37 | "eslint-plugin-node": "^11.0.0", 38 | "eslint-plugin-promise": "^4.0.1", 39 | "eslint-plugin-standard": "^4.0.0", 40 | "eslint-plugin-vue": "^6.1.2", 41 | "lottie-web": "^5.7.3", 42 | "vue-count-to": "^1.0.13", 43 | "vue-echarts": "^5.0.0-beta.0", 44 | "vue-json-views": "^1.3.0" 45 | }, 46 | "browserslist": [ 47 | "ie >= 11", 48 | "last 10 Chrome versions", 49 | "last 10 Firefox versions", 50 | "last 4 Edge versions", 51 | "last 7 Safari versions", 52 | "last 8 Android versions", 53 | "last 8 ChromeAndroid versions", 54 | "last 8 FirefoxAndroid versions", 55 | "last 10 iOS versions", 56 | "last 5 Opera versions" 57 | ], 58 | "engines": { 59 | "node": ">= 10.18.1", 60 | "npm": ">= 6.13.4", 61 | "yarn": ">= 1.21.1" 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /public/data/markdownData.md: -------------------------------------------------------------------------------- 1 |

Markdown Editor built on Vue

2 | 3 |

4 | Downloads 5 | Version 6 | License 7 |

8 | 9 | ## Links 10 | 11 | - [Demo](https://code-farmer-i.github.io/vue-markdown-editor/examples/base-editor.html) 12 | - [中文文档](https://code-farmer-i.github.io/vue-markdown-editor/zh/) 13 | - [更新日志](https://code-farmer-i.github.io/vue-markdown-editor/zh/changelog.html) 14 | 15 | ## 如何安装 16 | 17 | ```bash 18 | # 1. 项目中使用 19 | 找到 package.json 20 | devDependencies: { 21 | ... 22 | "@kangc/v-md-editor": "1.4.10" //最新版 2020.10 23 | } 24 | 执行: 25 | npm install 26 | 27 | # 2. use npm 28 | npm i @kangc/v-md-editor -S 29 | 30 | # 3. use yarn 31 | yarn add @kangc/v-md-editor 32 | ``` 33 | 34 | ## 快速开始 35 | 36 | ```js 37 | import Vue from 'vue'; 38 | import VueMarkdownEditor from '@kangc/v-md-editor'; 39 | import '@kangc/v-md-editor/lib/style/base-editor.css'; 40 | import vuepressTheme from '@kangc/v-md-editor/lib/theme/vuepress.js'; 41 | // 使用 vuepressTheme 主题 42 | VueMarkdownEditor.use(vuepressTheme); 43 | 44 | Vue.use(VueMarkdownEditor); 45 | ``` 46 | 47 | ## 使用 48 | 49 | ```html 50 | 53 | 54 | 63 | ``` 64 | 65 | ## 引用 66 | 67 | - [ElementUi Scrollbar Component](https://github.com/ElemeFE/element/tree/dev/packages/scrollbar) 68 | - [vuepress-plugin-container](https://vuepress.github.io/zh/plugins/container/) 69 | -------------------------------------------------------------------------------- /.devTools/shell-chrome/src/devtools.js: -------------------------------------------------------------------------------- 1 | // this script is called when the VueDevtools panel is activated. 2 | 3 | import { initDevTools } from '@front' 4 | import Bridge from '@utils/bridge' 5 | 6 | initDevTools({ 7 | 8 | /** 9 | * Inject backend, connect to background, and send back the bridge. 10 | * 11 | * @param {Function} cb 12 | */ 13 | 14 | connect (cb) { 15 | // 1. inject backend code into page 16 | injectScript(chrome.runtime.getURL('build/backend.js'), () => { 17 | // 2. connect to background to setup proxy 18 | const port = chrome.runtime.connect({ 19 | name: '' + chrome.devtools.inspectedWindow.tabId 20 | }) 21 | let disconnected = false 22 | port.onDisconnect.addListener(() => { 23 | disconnected = true 24 | }) 25 | 26 | const bridge = new Bridge({ 27 | listen (fn) { 28 | port.onMessage.addListener(fn) 29 | }, 30 | send (data) { 31 | if (!disconnected) { 32 | // if (process.env.NODE_ENV !== 'production') { 33 | // console.log('[chrome] devtools -> backend', data) 34 | // } 35 | port.postMessage(data) 36 | } 37 | } 38 | }) 39 | // 3. send a proxy API to the panel 40 | cb(bridge) 41 | }) 42 | }, 43 | 44 | /** 45 | * Register a function to reload the devtools app. 46 | * 47 | * @param {Function} reloadFn 48 | */ 49 | 50 | onReload (reloadFn) { 51 | chrome.devtools.network.onNavigated.addListener(reloadFn) 52 | } 53 | }) 54 | 55 | /** 56 | * Inject a globally evaluated script, in the same context with the actual 57 | * user app. 58 | * 59 | * @param {String} scriptName 60 | * @param {Function} cb 61 | */ 62 | 63 | function injectScript (scriptName, cb) { 64 | const src = ` 65 | (function() { 66 | var script = document.constructor.prototype.createElement.call(document, 'script'); 67 | script.src = "${scriptName}"; 68 | document.documentElement.appendChild(script); 69 | script.parentNode.removeChild(script); 70 | })() 71 | ` 72 | chrome.devtools.inspectedWindow.eval(src, function (res, err) { 73 | if (err) { 74 | console.log(err) 75 | } 76 | cb() 77 | }) 78 | } 79 | -------------------------------------------------------------------------------- /.devTools/shell-chrome/build/devtools-background.js: -------------------------------------------------------------------------------- 1 | (function(e){var n={};function t(o){if(n[o])return n[o].exports;var r=n[o]={i:o,l:!1,exports:{}};return e[o].call(r.exports,r,r.exports,t),r.l=!0,r.exports}t.m=e,t.c=n,t.d=function(e,n,o){t.o(e,n)||Object.defineProperty(e,n,{enumerable:!0,get:o})},t.r=function(e){"undefined"!==typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},t.t=function(e,n){if(1&n&&(e=t(e)),8&n)return e;if(4&n&&"object"===typeof e&&e&&e.__esModule)return e;var o=Object.create(null);if(t.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:e}),2&n&&"string"!=typeof e)for(var r in e)t.d(o,r,function(n){return e[n]}.bind(null,r));return o},t.n=function(e){var n=e&&e.__esModule?function(){return e["default"]}:function(){return e};return t.d(n,"a",n),n},t.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},t.p="",t(t.s=260)})({260:function(e,n){var t,o=!1,r=!1,u=!1,i=0;chrome.devtools.network.onNavigated.addListener(c);var a=setInterval(c,1e3);function c(){u||i++>10?clearInterval(a):(o=!1,r=!1,chrome.devtools.inspectedWindow.eval("!!(window.__VUE_DEVTOOLS_GLOBAL_HOOK__.Vue)",function(e){e&&!u&&(clearInterval(a),u=!0,chrome.devtools.panels.create("Vue","icons/128.png","devtools.html",e=>{e.onShown.addListener(v),e.onHidden.addListener(p)}))}))}function l(e){var n=e.id;if("vue-inspect-instance"===n){var o="window.__VUE_DEVTOOLS_CONTEXT_MENU_HAS_TARGET__";chrome.devtools.inspectedWindow.eval(o,function(e,n){n&&console.log(n),"undefined"!==typeof e&&e?d(()=>{chrome.runtime.sendMessage("vue-get-context-menu-target")},"Open Vue devtools to see component details"):(t=null,_("No Vue component was found","warn"))})}}function d(e,n=null){u&&o&&r?e():(t=e,n&&_(n))}function s(){t&&t(),t=null}function f(){s(),o=!0}function v(){chrome.runtime.sendMessage("vue-panel-shown"),r=!0,o&&s()}function p(){chrome.runtime.sendMessage("vue-panel-hidden"),r=!1}function _(e,n="normal"){var t=`(function() {\n __VUE_DEVTOOLS_TOAST__(\`${e}\`, '${n}');\n })()`;chrome.devtools.inspectedWindow.eval(t,function(e,n){n&&console.log(n)})}c(),chrome.runtime.onMessage.addListener(e=>{"vue-panel-load"===e?f():e.vueToast?_(e.vueToast.message,e.vueToast.type):e.vueContextMenu&&l(e.vueContextMenu)})}}); -------------------------------------------------------------------------------- /src/router/index.js: -------------------------------------------------------------------------------- 1 | // import Vue from 'vue' 2 | // import VueRouter from 'vue-router' 3 | // import constantRoutes from 'src/router/constantRoutes' 4 | // 5 | // Vue.use(VueRouter) 6 | // 7 | // /* 8 | // * If not building with SSR mode, you can 9 | // * directly export the Router instantiation; 10 | // * 11 | // * The function below can be async too; either use 12 | // * async/await or return a Promise which resolves 13 | // * with the Router instance. 14 | // */ 15 | // 16 | // /** 17 | // * Reset route when user logs out 18 | // */ 19 | // export function resetRouter () { 20 | // const newRouter = createRouter() 21 | // router.matcher = newRouter.matcher 22 | // } 23 | // 24 | // const createRouter = () => new VueRouter({ 25 | // scrollBehavior: () => ({ x: 0, y: 0 }), 26 | // constantRoutes, 27 | // 28 | // // Leave these as they are and change in quasar.conf.js instead! 29 | // // quasar.conf.js -> build -> vueRouterMode 30 | // // quasar.conf.js -> build -> publicPath 31 | // mode: process.env.VUE_ROUTER_MODE, 32 | // base: process.env.VUE_ROUTER_BASE 33 | // }) 34 | // 35 | // // eslint-disable-next-line no-void 36 | // let router = void 0 37 | // export default async function (/* { store, ssrContext } */) { 38 | // const Router = createRouter() 39 | // router = Router 40 | // return Router 41 | // } 42 | // 43 | // console.log(13, router) 44 | // 45 | // export { router } 46 | 47 | import Vue from 'vue' 48 | import VueRouter from 'vue-router' 49 | import constantRoutes from './constantRoutes' 50 | 51 | Vue.use(VueRouter) 52 | 53 | // Solve the error when the routing guard is redirected 54 | const originalPush = VueRouter.prototype.push 55 | VueRouter.prototype.push = function push (location, onResolve, onReject) { 56 | if (onResolve || onReject) return originalPush.call(this, location, onResolve, onReject) 57 | return originalPush.call(this, location).catch(err => err) 58 | } 59 | 60 | // Reset route when user logs out 61 | export function resetRouter () { 62 | const newRouter = createRouter() 63 | router.matcher = newRouter.matcher 64 | } 65 | 66 | const createRouter = () => new VueRouter({ 67 | mode: process.env.VUE_ROUTER_MODE, 68 | base: process.env.BASE_URL, 69 | routes: constantRoutes 70 | }) 71 | 72 | const router = createRouter() 73 | 74 | export default router 75 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | // https://eslint.org/docs/user-guide/configuring#configuration-cascading-and-hierarchy 3 | // This option interrupts the configuration hierarchy at this file 4 | // Remove this if you have an higher level ESLint config file (it usually happens into a monorepos) 5 | root: true, 6 | 7 | parserOptions: { 8 | parser: 'babel-eslint', 9 | ecmaVersion: 2018, // Allows for the parsing of modern ECMAScript features 10 | sourceType: 'module' // Allows for the use of imports 11 | }, 12 | 13 | env: { 14 | browser: true 15 | }, 16 | 17 | // Rules order is important, please avoid shuffling them 18 | extends: [ 19 | // Base ESLint recommended rules 20 | // 'eslint:recommended', 21 | 22 | 23 | // Uncomment any of the lines below to choose desired strictness, 24 | // but leave only one uncommented! 25 | // See https://eslint.vuejs.org/rules/#available-rules 26 | 'plugin:vue/essential', // Priority A: Essential (Error Prevention) 27 | // 'plugin:vue/strongly-recommended', // Priority B: Strongly Recommended (Improving Readability) 28 | // 'plugin:vue/recommended', // Priority C: Recommended (Minimizing Arbitrary Choices and Cognitive Overhead) 29 | 30 | 'standard' 31 | 32 | ], 33 | 34 | plugins: [ 35 | // https://eslint.vuejs.org/user-guide/#why-doesn-t-it-work-on-vue-file 36 | // required to lint *.vue files 37 | 'vue', 38 | 39 | ], 40 | 41 | globals: { 42 | ga: true, // Google Analytics 43 | cordova: true, 44 | __statics: true, 45 | process: true, 46 | Capacitor: true, 47 | chrome: true 48 | }, 49 | 50 | // add your custom rules here 51 | rules: { 52 | // allow async-await 53 | 'generator-star-spacing': 'off', 54 | // allow paren-less arrow functions 55 | 'arrow-parens': 'off', 56 | 'one-var': 'off', 57 | 58 | 'import/first': 'off', 59 | 'import/named': 'error', 60 | 'import/namespace': 'error', 61 | 'import/default': 'error', 62 | 'import/export': 'error', 63 | 'import/extensions': 'off', 64 | 'import/no-unresolved': 'off', 65 | 'import/no-extraneous-dependencies': 'off', 66 | 'prefer-promise-reject-errors': 'off', 67 | 68 | 69 | // allow debugger during development only 70 | 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off' 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /.devTools/shell-chrome/build/background.js: -------------------------------------------------------------------------------- 1 | (function(e){var n={};function t(o){if(n[o])return n[o].exports;var r=n[o]={i:o,l:!1,exports:{}};return e[o].call(r.exports,r,r.exports,t),r.l=!0,r.exports}t.m=e,t.c=n,t.d=function(e,n,o){t.o(e,n)||Object.defineProperty(e,n,{enumerable:!0,get:o})},t.r=function(e){"undefined"!==typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},t.t=function(e,n){if(1&n&&(e=t(e)),8&n)return e;if(4&n&&"object"===typeof e&&e&&e.__esModule)return e;var o=Object.create(null);if(t.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:e}),2&n&&"string"!=typeof e)for(var r in e)t.d(o,r,function(n){return e[n]}.bind(null,r));return o},t.n=function(e){var n=e&&e.__esModule?function(){return e["default"]}:function(){return e};return t.d(n,"a",n),n},t.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},t.p="",t(t.s=259)})({259:function(e,n){var t,o={};function r(e){return+e+""===e}function c(e){chrome.tabs.executeScript(e,{file:"/build/proxy.js"},function(n){n?console.log("injected proxy to tab "+e):o[e].devtools.postMessage("proxy-fail")})}function s(e,n,t){function r(n){if("log"===n.event)return console.log("tab "+e,n.payload);console.log("devtools -> backend",n),t.postMessage(n)}function c(t){if("log"===t.event)return console.log("tab "+e,t.payload);console.log("backend -> devtools",t),n.postMessage(t)}function s(){console.log("tab "+e+" disconnected."),n.onMessage.removeListener(r),t.onMessage.removeListener(c),n.disconnect(),t.disconnect(),o[e]=null,a()}n.onMessage.addListener(r),t.onMessage.addListener(c),n.onDisconnect.addListener(s),t.onDisconnect.addListener(s),console.log("tab "+e+" connected."),a()}function a(){chrome.contextMenus.removeAll(()=>{o[t]&&chrome.contextMenus.create({id:"vue-inspect-instance",title:"Inspect Vue component",contexts:["all"]})})}chrome.runtime.onConnect.addListener(e=>{var n,t;r(e.name)?(n=e.name,t="devtools",c(+e.name)):(n=e.sender.tab.id,t="backend"),o[n]||(o[n]={devtools:null,backend:null}),o[n][t]=e,o[n].devtools&&o[n].backend&&s(n,o[n].devtools,o[n].backend)}),chrome.runtime.onMessage.addListener((e,n)=>{if(n.tab&&e.vueDetected){var t=e.nuxtDetected?".nuxt":"";chrome.browserAction.setIcon({tabId:n.tab.id,path:{16:`icons/16${t}.png`,48:`icons/48${t}.png`,128:`icons/128${t}.png`}}),chrome.browserAction.setPopup({tabId:n.tab.id,popup:e.devtoolsEnabled?`popups/enabled${t}.html`:`popups/disabled${t}.html`})}}),chrome.tabs.onActivated.addListener(e=>{var n=e.tabId;t=n,a()}),chrome.contextMenus.onClicked.addListener((e,n)=>{chrome.runtime.sendMessage({vueContextMenu:{id:e.menuItemId}})})}}); -------------------------------------------------------------------------------- /public/data/breadcrumbsData.md: -------------------------------------------------------------------------------- 1 | ## breadcrumbs 面包屑 2 | ```sh 3 | components 4 | |-Breadcrumbs 5 | |-Breadcrumbs.vue # Breadcrumb 源文件 6 | |-BreadcrumbsUtils.js # 设置 Breadcrumbs 工具类 7 | ``` 8 | :::tip 9 | - 面包屑的路径信息是在路由守卫中通过深拷贝```to.matched```属性而来。 10 | - 当路由跳转带```query```参数时,```breadcrumbs```标签会加上第一个参数的值,作为标识 11 | ::: 12 | 13 | 但为了实现``````缓存,需要将```to.matched```做了拍平处理(详见 ```缓存```说明),此时```to.matched```被拍平之后失去了父组件的路由元信息,这样在实现面包屑功能时无法做到如 14 | 15 | 组件说明 / 面包屑 16 | ```(父路由)```/```(子路由)``` 17 | 18 | 的地址展示。 19 | 20 | 因此在进行路由拍平之前,需要保存```to.matched```,因此在Vuex中维护了一个```breadcrumbs:[]```,用来记录当前页面的路径信息。 21 | 22 | 并且在每次路由守卫中更新这个```breadcrumbs:[]```就能保证当前页面的路径能正常显示。 23 | 24 | 关键代码 25 | ```js 26 | router.beforeEach((to, from, next) => { 27 | ... 28 | setBreadcrumbs(to.matched, to.query) 29 | ... 30 | }) 31 | 32 | ## BreadcrumbsUtils.js 33 | /** 34 | * 获取 matched 中的路径 title,并生成面包屑 35 | * 如果有 query 则取第一个参数附加在 title 上 36 | * @param matched to.matched[] 37 | * @param query 参数 38 | */ 39 | export function setBreadcrumbs (matched, query) { 40 | const temp = [] 41 | for (let i = 0; i < matched.length; i++) { 42 | temp.push(deepClone(matched[i].meta)) 43 | } 44 | const last = temp.length - 1 45 | // 如果有 query 则取第一个参数附加在 title 上 46 | Object.keys(query).length && (temp[last].title += ':' + getFirst(query)) 47 | store.commit('SET_BREADCRUMBS', temp) 48 | } 49 | ``` 50 | 51 | ### 动画效果 52 | 动画效果使用的是 `````` 53 | 54 | ``````和 ``````的区别就是: 55 | - ``````中只能有一个元素,``````使用动画控制这个唯一元素的消失与出现 56 | - ``````中可以有多个元素,通常是通过```v-for```生成的元素 57 | ``````控制着每一个子元素的消失与出现,但是``````有一定局限,被控制的元素会被``````自动生成的``````或```
    ```标签包裹,这样会对css样式产生一定的影响。 58 | 59 | 60 | 关于``````和 ``````标签的使用并不难,使用关键帧和过度态来理解它或很容易,详情请看[VUE:进入/离开 & 列表过渡](https://cn.vuejs.org/v2/guide/transitions.html) 61 | 62 | 动画定义如下: 63 | ```assets/scss/transitions.scss``` 64 | ```css 65 | .breadcrumb-enter { 66 | opacity: 0; 67 | transform: translateX(30px); 68 | } 69 | 70 | .breadcrumb-enter-active { 71 | transition: all .5s; 72 | } 73 | 74 | .breadcrumb-enter-to { 75 | opacity: 1; 76 | } 77 | 78 | .breadcrumb-leave { 79 | opacity: 1; 80 | transform: translateX(0px); 81 | } 82 | 83 | .breadcrumb-move { 84 | transition: all .5s; 85 | } 86 | 87 | .breadcrumb-leave-active{ 88 | transition: all .5s; 89 | position: absolute; 90 | width: 500px; 91 | } 92 | 93 | .breadcrumb-leave-to{ 94 | opacity: 0; 95 | transform: translateX(30px); 96 | } 97 | 98 | ``` 99 | -------------------------------------------------------------------------------- /src/layouts/MainLayout.vue: -------------------------------------------------------------------------------- 1 | 54 | 55 | 95 | -------------------------------------------------------------------------------- /public/data/tagViewData.md: -------------------------------------------------------------------------------- 1 | ## tagView 2 | 在SPA中因为减少了浏览器跳转,所以```tagView```的存在是必要的 3 | :::tip 4 | - 鼠标右键可以打开 ```tagView``` 上下文菜单,移动端下则是长按打开上下文菜单 5 | - 当路由跳转带```query```参数时,```tagView```标签会加上第一个参数的值,作为标识 6 | ::: 7 | 8 | ```tagview```位置 9 | ```sh 10 | components 11 | |-TagView 12 | |-tagView.vue # tagView 源文件 13 | |-TagViewUtils.js # tagView 工具类: 增/删 14 | ``` 15 | 16 | 本项目中```tagView ```的作用不只是作为快捷导航使用。同时还作为页面缓存``````中的标识使用,即,有 ```tagView```存在的话则对应页面的缓存也存在(该路由元信息中声明了```keepAlive: false```除外), ```tagView```被关闭则对应页面缓存将被从内存中清除 17 | 18 | 在```Vuex```中维护了两个数组:```tagView: []```、```keepAliveList: []```,其中```tagView: []```保存的是访问过的路由信息,```keepAliveList: []```则是需要被缓存组件列表。 19 | 20 | ```tagView: []```结构如下: 21 | 22 | ![在这里插入图片描述](https://img-blog.csdnimg.cn/20201109193512403.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQxOTEyMzk4,size_16,color_FFFFFF,t_70#pic_center) 23 | 24 | ```keepAliveList: []```则是由从```tagView: []```中抽取 ```keepAlive === true```的元素的```name```,组成的 25 | 26 | ![在这里插入图片描述](https://img-blog.csdnimg.cn/20201109193935667.png#pic_center) 27 | 28 | 项目会```watch```每一次```tagView[]```的变化,并组成新的```keepAliveList: []``` 29 | 30 | 具体如何实现缓存,请看```keep-alive 缓存```说明 31 | 32 | 33 | tagView的实现并不复杂,不过处理逻辑挺复杂的,比如: 34 | 1.如果被关闭的```tagView```是当前组件,应该作何反应 35 | 2.如果被关闭的```tagView```是第一个或最后一个,应该作何反应,如果不是,又作何反应 36 | 3.关闭左侧,关闭右侧,关闭全部等操作 37 | 4.当路由跳转带参数时```tagView```作何处理 38 | 4.如何适配移动端等 39 | 40 | 下面是```tagView```事件处理入口,如果需要,请自行修改 41 | 42 | 在```mutations.js```中,```removeOneSide```和```removeATagView```方法来自```TagViewUtils.js``` 43 | ```js 44 | /** 45 | * 移除 tagView 46 | * case 'undefined' : 移除所有 tagView 47 | * case 'object' : 移除某一侧 tagView 或两侧都移除 48 | * default '要删除元素的下标 i ' : 移除第 i 一个 tagView 49 | * 如果移除的是第一个 tagView,则跳转到当前的第一个 tagView 50 | * 如果移除的是最后一个 tagView,则跳转到当前的最后一个 tagView 51 | * 否则返回主页 52 | * @param state 53 | * @param payload 54 | * @constructor 55 | */ 56 | REMOVE_TAG_VIEW: (state, payload) => { 57 | switch (typeof payload) { 58 | case 'undefined': 59 | state.tagView = [] 60 | router.push('/') 61 | break 62 | case 'object': 63 | removeOneSide(state, payload) 64 | break 65 | default: 66 | removeATagView(state, payload) 67 | } 68 | } 69 | ``` 70 | 在组件中调用 71 | ```js 72 | // 调用方法 73 | methods: { 74 | removeAllTagView () { 75 | this.$store.commit('REMOVE_TAG_VIEW') 76 | }, 77 | removeLeftTagView (i) { 78 | this.$store.commit('REMOVE_TAG_VIEW', { side: 'left', index: i }) 79 | }, 80 | removeRightTagView (i) { 81 | this.$store.commit('REMOVE_TAG_VIEW', { side: 'right', index: i }) 82 | }, 83 | removeOthersTagView (i) { 84 | this.$store.commit('REMOVE_TAG_VIEW', { side: 'others', index: i }) 85 | } 86 | } 87 | ``` 88 | 89 | 90 | -------------------------------------------------------------------------------- /src/components/BaseContent/BaseContent.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 95 | -------------------------------------------------------------------------------- /src/pages/lottie/lottie.vue: -------------------------------------------------------------------------------- 1 | 40 | 41 | 101 | -------------------------------------------------------------------------------- /src/assets/js/echarts-4.js: -------------------------------------------------------------------------------- 1 | const echarts = require('echarts/lib/echarts') 2 | 3 | const option = { 4 | backgroundColor: '#fff', 5 | grid: { 6 | top: '100', 7 | right: '40', 8 | left: '60', 9 | bottom: '40' // 图表尺寸大小 10 | }, 11 | xAxis: [{ 12 | type: 'category', 13 | color: '#59588D', 14 | data: ['Q1', 'Q2', 'Q3', 'Q4', 'Q5', 'Q6', 'Q7', 'Q8'], 15 | axisLabel: { 16 | margin: 10, 17 | color: '#999', 18 | textStyle: { 19 | fontSize: 12 20 | } 21 | }, 22 | axisLine: { 23 | lineStyle: { 24 | color: 'rgba(107,107,107,0.37)' 25 | } 26 | }, 27 | axisTick: { 28 | show: false 29 | } 30 | }], 31 | yAxis: [{ 32 | axisLabel: { 33 | formatter: '{value}%', 34 | color: '#999', 35 | textStyle: { 36 | fontSize: 12 37 | } 38 | }, 39 | axisLine: { 40 | lineStyle: { 41 | color: 'rgba(107,107,107,0.37)' 42 | } 43 | }, 44 | axisTick: { 45 | show: false 46 | }, 47 | splitLine: { 48 | lineStyle: { 49 | color: 'rgba(131,101,101,0.2)', 50 | type: 'dashed' 51 | } 52 | } 53 | }], 54 | series: [{ 55 | type: 'bar', 56 | data: [40, 80, 50, 36, 30, 35, 40, 60], 57 | barWidth: '16px', 58 | itemStyle: { 59 | normal: { 60 | color: function (params) { // 展示正值的柱子,负数设为透明 61 | const colorArr = params.value > 0 ? ['#55d1ff', '#2d82ff'] : ['rgba(0,0,0,0)', 'rgba(0,0,0,0)'] 62 | return new echarts.graphic.LinearGradient(0, 0, 0, 1, [{ 63 | offset: 0, 64 | color: colorArr[0] // 0% 处的颜色 65 | }, { 66 | offset: 1, 67 | color: colorArr[1] // 100% 处的颜色 68 | }], false) 69 | }, 70 | barBorderRadius: [30, 30, 0, 0] // 圆角大小 71 | } 72 | }, 73 | label: { 74 | normal: { 75 | show: true, 76 | fontSize: 16, 77 | fontWeight: 'bold', 78 | color: '#333', 79 | position: 'top' 80 | } 81 | } 82 | }, { 83 | data: [40, 60, 40, 36, 30, 35, 40, 60], 84 | type: 'line', 85 | smooth: true, 86 | name: '折线图', 87 | symbol: 'none', 88 | lineStyle: { 89 | color: '#3275FB', 90 | width: 3, 91 | shadowColor: 'rgba(0, 0, 0, 0.3)', // 设置折线阴影 92 | shadowBlur: 10, 93 | shadowOffsetY: 10 94 | }, 95 | areaStyle: { 96 | normal: { 97 | color: new echarts.graphic.LinearGradient( 98 | 0, 99 | 0, 100 | 0, 101 | 1, 102 | [{ 103 | offset: 0, 104 | color: 'rgba(73, 86, 255, 0.5)' 105 | 106 | }, 107 | { 108 | offset: 1, 109 | color: 'rgba(255, 255, 255, 0.1)' 110 | } 111 | ], 112 | false 113 | ) 114 | 115 | } 116 | } 117 | }] 118 | } 119 | 120 | export default option 121 | -------------------------------------------------------------------------------- /src/axios/AxiosConfig.js: -------------------------------------------------------------------------------- 1 | import Axios from 'axios' 2 | import Vue from 'vue' 3 | import { Notify } from 'quasar' 4 | import qs from 'qs' 5 | 6 | /** 7 | * axios initialization 8 | */ 9 | const axios = Axios.create({ 10 | // baseURL: Vue.prototype.$baseURL, 11 | timeout: Vue.prototype.$timeOut 12 | }) 13 | 14 | axios.interceptors.request.use( 15 | config => { 16 | const token = sessionStorage.getItem('access_token') 17 | config.headers.Authorization = 'Bearer ' + token 18 | if (config.type) { 19 | switch (config.type) { 20 | case 'FORM-DATA': 21 | config.transformRequest = [data => { return 'args=' + JSON.stringify(data) }] 22 | break 23 | case 'FORM': 24 | config.headers['Content-Type'] = 'application/x-www-form-urlencoded' 25 | config.data = qs.stringify(config.data) 26 | break 27 | default: 28 | break 29 | } 30 | } 31 | return config 32 | }, 33 | error => { 34 | return Promise.reject(error) 35 | } 36 | ) 37 | 38 | axios.interceptors.response.use( 39 | response => { 40 | return response 41 | }, 42 | error => { 43 | const defaultNotify = { 44 | message: '未知错误', 45 | icon: 'warning', 46 | color: 'warning', 47 | position: 'top', 48 | timeout: 1500 49 | } 50 | if (error.code === 'ECONNABORTED' || error.message.indexOf('timeout') !== -1 || error.message === 'Network Error') { 51 | defaultNotify.message = '网络异常' 52 | Notify.create(defaultNotify) 53 | return Promise.reject(error) 54 | } 55 | switch (error.response.status) { 56 | case 403: 57 | defaultNotify.message = '拒绝访问(403)' 58 | Notify.create(defaultNotify) 59 | break 60 | case 404: 61 | defaultNotify.message = '资源不存在(404)' 62 | Notify.create(defaultNotify) 63 | break 64 | case 408: 65 | defaultNotify.message = '请求超时(408)' 66 | Notify.create(defaultNotify) 67 | break 68 | case 500: 69 | defaultNotify.message = '服务器错误(500)' 70 | Notify.create(defaultNotify) 71 | break 72 | case 501: 73 | defaultNotify.message = '服务未实现(501)' 74 | Notify.create(defaultNotify) 75 | break 76 | case 502: 77 | defaultNotify.message = '网络错误(502)' 78 | Notify.create(defaultNotify) 79 | break 80 | case 503: 81 | defaultNotify.message = '服务不可用(503)' 82 | Notify.create(defaultNotify) 83 | break 84 | case 504: 85 | defaultNotify.message = '网络超时(504)' 86 | Notify.create(defaultNotify) 87 | break 88 | case 505: 89 | defaultNotify.message = 'HTTP版本不受支持(505)' 90 | Notify.create(defaultNotify) 91 | break 92 | default: 93 | Notify.create(defaultNotify) 94 | break 95 | } 96 | return Promise.reject(error) 97 | } 98 | ) 99 | 100 | export default axios 101 | -------------------------------------------------------------------------------- /.devTools/shell-electron/app.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Vue Developer Tools 6 | 71 | 72 | 73 |
    74 | 75 |

    76 | Waiting for connection... 77 |

    78 |
    79 |
    80 | 81 | 82 |
    83 |
    84 | 85 | 86 |
    87 | to the top of the page you want to debug. 88 |
    89 |
    90 |
    91 |
    92 | 111 | 112 | 113 | 114 | -------------------------------------------------------------------------------- /public/data/scrollData.md: -------------------------------------------------------------------------------- 1 | ## 滚动区域 BaseContent 2 | ```sh 3 | components 4 | |-BaseContent 5 | |-BaseContent.vue # BaseContent 源文件 6 | ``` 7 | ```BaseContent```也是自己封装一个用于内容展示的组件,所有的组件都建议用```BaseContent```作为根节点,主要是为了实现: 8 | - 特点区域的滚动 9 | - 组件缓存 10 | - 界面缩放/滚动自适应 11 | - 直接点击滚动栏对应位置即可快速定位 12 | - 页面刷新或切换时记录滚动位置(如果页面不被``````缓存则不会记录) 13 | 14 | 因为我在百度统计里看到大家对这个组件的比较感兴趣,干脆直接在这里上源码和注释吧 15 | ```html 16 | 28 | 29 | 105 | 111 | ``` 112 | 113 | :::tip 114 | 如果你对滚动位置记录没有要求,或是需求不同,可以把相关代码注释掉,甚至是根据它来自己做一个 ```BaseContent```组件 115 | 因为我感觉这个组件太过的针对性,反而对于新手来说不好改 116 | ::: 117 | -------------------------------------------------------------------------------- /public/data/iconData.md: -------------------------------------------------------------------------------- 1 | Quasar支持:Material Icons、Font Awesome、Ionicons、MDI、Eva Icons和Themify Icons。 2 | 这个项目的图标集使用的是quasar自带的material design和fontawesome-v5图标集 3 | 4 | [[toc]] 5 | 6 | ### 使用方式 7 | ```html 8 | 9 | 10 | 11 | 12 | 13 | ``` 14 | 几乎所有的组件都提供了icon属性来设置图标 15 | 16 | 如果想要使用Quasar的其他图标集合,请在```quasar.js```里添加对于的依赖即可使用,关于图标的依赖都在```quasar/extras```目录下,比如我想要使用mdi-v4图标集 17 | 18 | ```js 19 | import '@quasar/extras/mdi-v4/mdi-v4.css' 20 | ``` 21 | 22 | ### 注意,需要使用全小写才能正确使用图标 23 | 在导入图标集合是发现,集合导出的图标名称是驼峰命名的,但是在quasar里使用驼峰命名的图标会出问题,比如: 24 | 图标名为 ArrowUpward 时 25 | 需要为 `````` 才能正确使用 26 | ### 如果你想制作一个图标集合界面,就需要对导出的图标集合名词进行修改,使用正则是最方便的修改方式 27 | ```js 28 | // 下面是针对 material 和 fontawesome-v5 图标集的修改 29 | // 驼峰转 - 连接,并且添加' fa-'前缀 30 | toLowerLine (str) { 31 | if (str.substr(0, 3) === 'mat') { 32 | return str.replace(/([A-Z]|\d+)/g, (a, l) => `_${l.toLowerCase()}`).substring(4) 33 | } 34 | if (str.substr(0, 2) === 'fa') { 35 | return str.replace(/([A-Z]|\d+)/g, (a, l) => `-${l.toLowerCase()}`).replace(/-/, ' fa-') 36 | } 37 | } 38 | ``` 39 | 40 | ### 当然你也可以使用第三方工具包,比如:``name-styles`` 41 | 42 | ```js 43 | import { 44 | camel, 45 | pascal, 46 | hyphen, 47 | snake 48 | } from "name-styles"; 49 | 50 | const s = "Hello Name-Styles"; 51 | 52 | camel(s); 53 | // helloNameStyles 54 | 55 | pascal(s); 56 | // HelloNameStyles 57 | 58 | hyphen(s); 59 | // hello-name-styles 60 | 61 | snake(s); 62 | // hello_name_styles 63 | ``` 64 | 65 | 下面是quasar对各个图标集图标名称的限制(我也不知道为啥要加这些限制) 66 | 67 | | Quasar IconSet name | Name prefix | Examples | Notes | 68 | | --- | --- | --- | --- | 69 | | material-icons | *None* | thumb_up | Notice the underline character instead of dash or space | 70 | | material-icons-outlined | o_ | o_thumb_up | Notice the underline character instead of dash or space; **Quasar 1.0.5+** | 71 | | material-icons-round | r_ | r_thumb_up | Notice the underline character instead of dash or space; **Quasar 1.0.5+** | 72 | | material-icons-sharp | s_ | s_thumb_up | Notice the underline character instead of dash or space; **Quasar 1.0.5+** | 73 | | ionicons-v4 | ion-, ion-md-, ion-ios-, ion-logo- | ion-heart, ion-logo-npm, ion-md-airplane | Use QIcon instead of `` component; Logo icons require 'ion-logo-' prefix | 74 | | fontawesome-v5 | fa[s,r,l,d,b] fa- | "fas fa-ambulance" | QIcon "name" property is same as "class" attribute value in Fontawesome docs examples (where they show `` tags) | 75 | | mdi-v5/v4/v3 | mdi- | mdi-alert-circle-outline | Notice the use of dash characters; Use only one of mdi-v5, mdi-v4 or mdi-v3 | 76 | | eva-icons | eva- | eva-shield-outline, eva-activity-outline | Notice the use of dash characters | 77 | | themify | ti- | ti-hand-point-up | Notice the use of dash characters | 78 | | line-awesome | la[s,r,l,d,b] la- | "las la-atom" | QIcon "name" property is same as "class" attribute value in Line Awesome docs examples (where they show `` tags); 79 | 80 | ### 当然你也可以使用iconfont图标集 81 | 使用iconfont图标集的方式在百度上都有,而且很简单,需要的话自己整合即可 82 | -------------------------------------------------------------------------------- /src/components/TagView/TagViewUtils.js: -------------------------------------------------------------------------------- 1 | import store from '../../store/index' 2 | import router from '../../router' 3 | import { getFirst } from 'src/utils/CloneUtils' 4 | 5 | /** 6 | * Construct the meta-information of the tagView,and submit it to the store, 7 | * if it meets the conditions (not a public route), generate the tagView element 8 | * @param to 9 | */ 10 | export function addTagView (to) { 11 | // Construct a temporary tagView object 12 | const t = { 13 | fullPath: to.fullPath, 14 | name: to.name, 15 | title: to.meta.title, 16 | icon: to.meta.icon, 17 | keepAlive: to.meta.keepAlive || false 18 | } 19 | // If there are parameters, add the first parameter to the title 20 | getFirst(to.query) !== undefined && (t.title += ':' + getFirst(to.query)) 21 | if (t.title !== null && t.title !== undefined && t.fullPath !== '/' && t.fullPath.indexOf('#') === -1) { 22 | store.commit('ADD_TAG_VIEW', t) 23 | } 24 | } 25 | 26 | /** 27 | * if it is a refresh operation, get the saved tagView information from sessionStorage 28 | * then call this method 29 | * @param tagView 30 | */ 31 | export function setTagView (tagView) { 32 | store.commit('SET_TAG_VIEW', tagView) 33 | } 34 | 35 | /** 36 | * Only remove one tagView 37 | * @param state 38 | * @param payload 39 | */ 40 | export function removeATagView (state, payload) { 41 | // Record removed routes 42 | const removedTagView = state.tagView[payload].fullPath 43 | state.tagView.splice(payload, 1) 44 | // If tagView is empty 45 | if (state.tagView.length === 0) { 46 | window.sessionStorage.setItem('tagView', '[]') 47 | router.push('/') 48 | } else { 49 | // If the last tagView is removed, the route jumps to the current last tagView 50 | if (payload === state.tagView.length && window.location.href.indexOf(removedTagView) !== -1) { 51 | router.push(state.tagView[payload - 1].fullPath) 52 | return 53 | } 54 | // If the first tagView is removed, the route jumps to the next tagView 55 | if (payload === 0 && window.location.href.indexOf(removedTagView) !== -1) { 56 | router.push(state.tagView[0].fullPath) 57 | return 58 | } 59 | if (window.location.href.indexOf(removedTagView) !== -1) { 60 | router.push(state.tagView[payload - 1].fullPath) 61 | } 62 | } 63 | } 64 | 65 | /** 66 | * Remove one side of tagView 67 | * @param state 68 | * @param payload 69 | */ 70 | export function removeOneSide (state, payload) { 71 | switch (payload.side) { 72 | case 'right': 73 | state.tagView = state.tagView.slice(0, payload.index + 1) 74 | if (state.tagView.length === 1) { 75 | router.push(state.tagView[0].fullPath) 76 | } 77 | if (state.tagView.length === payload.index + 1) { 78 | router.push(state.tagView[payload.index].fullPath) 79 | } 80 | break 81 | case 'left': 82 | state.tagView = state.tagView.slice(payload.index, state.tagView.length) 83 | if (state.tagView.length === 1) { 84 | router.push(state.tagView[0].fullPath) 85 | } 86 | if (state.tagView.length <= payload.index) { 87 | router.push(state.tagView[0].fullPath) 88 | } 89 | break 90 | case 'others': 91 | state.tagView = state.tagView.splice(payload.index, 1) 92 | router.push(state.tagView[0].fullPath) 93 | break 94 | default: 95 | break 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /public/data/lottieData.md: -------------------------------------------------------------------------------- 1 | ## Lottie 2 | Lottie 是能将 json 格式的动画文件,渲染成为能在前端显示的工具。 3 | 4 | 而这些 json 格式的动画文件通常来自于 After Effects 渲染的动画特效。设计师们在 After Effects 上完成动画后,通过 After Effects 上的 Bodymovin 插件就能把动画生成为json格式。 5 | 6 | Lottie 的动效常用在动态图标,开屏展示等需要用户交互体验比较高的地方。 7 | 8 | 同时它还提供了 js/android/ios 等不同环境的开发工具包,在不同的环境下都能愉快的使用动效 9 | ### Github 仓库 10 | - [lottie-web](https://github.com/airbnb/lottie-web) 11 | - [lottie-ios](https://github.com/airbnb/lottie-ios) 12 | - [lottie-android](https://github.com/airbnb/lottie-android) 13 | ### 如何使用 14 | - 在```package.json```中添加依赖 15 | ```js 16 | "devDependencies": { 17 | ... 18 | // 请尽量使用原始的,网络上封装的质量不太好(踩坑了) 19 | "lottie-web": "^5.7.3" 20 | } 21 | 22 | // 在控制台中安装到本项目 23 | npm install // or cnpm i 24 | ``` 25 | ### 我根据自身的需求封装一个 lottie 组件 26 | 27 | :::tip 28 | 尽量使用 path 导入动画文件,这样做能减小不必要的体积,而且能避免 lottie 重复执行动画 29 | ::: 30 | ```html 31 | 34 | 35 | 97 | ``` 98 | ### 如何使用 99 | ```html 100 | 107 | 108 | 140 | ``` 141 | -------------------------------------------------------------------------------- /.devTools/shell-chrome/src/background.js: -------------------------------------------------------------------------------- 1 | // the background script runs all the time and serves as a central message 2 | // hub for each vue devtools (panel + proxy + backend) instance. 3 | 4 | const ports = {} 5 | 6 | chrome.runtime.onConnect.addListener(port => { 7 | let tab 8 | let name 9 | if (isNumeric(port.name)) { 10 | tab = port.name 11 | name = 'devtools' 12 | installProxy(+port.name) 13 | } else { 14 | tab = port.sender.tab.id 15 | name = 'backend' 16 | } 17 | 18 | if (!ports[tab]) { 19 | ports[tab] = { 20 | devtools: null, 21 | backend: null 22 | } 23 | } 24 | ports[tab][name] = port 25 | 26 | if (ports[tab].devtools && ports[tab].backend) { 27 | doublePipe(tab, ports[tab].devtools, ports[tab].backend) 28 | } 29 | }) 30 | 31 | function isNumeric (str) { 32 | return +str + '' === str 33 | } 34 | 35 | function installProxy (tabId) { 36 | chrome.tabs.executeScript(tabId, { 37 | file: '/build/proxy.js' 38 | }, function (res) { 39 | if (!res) { 40 | ports[tabId].devtools.postMessage('proxy-fail') 41 | } else { 42 | console.log('injected proxy to tab ' + tabId) 43 | } 44 | }) 45 | } 46 | 47 | function doublePipe (id, one, two) { 48 | one.onMessage.addListener(lOne) 49 | function lOne (message) { 50 | if (message.event === 'log') { 51 | return console.log('tab ' + id, message.payload) 52 | } 53 | console.log('devtools -> backend', message) 54 | two.postMessage(message) 55 | } 56 | two.onMessage.addListener(lTwo) 57 | function lTwo (message) { 58 | if (message.event === 'log') { 59 | return console.log('tab ' + id, message.payload) 60 | } 61 | console.log('backend -> devtools', message) 62 | one.postMessage(message) 63 | } 64 | function shutdown () { 65 | console.log('tab ' + id + ' disconnected.') 66 | one.onMessage.removeListener(lOne) 67 | two.onMessage.removeListener(lTwo) 68 | one.disconnect() 69 | two.disconnect() 70 | ports[id] = null 71 | updateContextMenuItem() 72 | } 73 | one.onDisconnect.addListener(shutdown) 74 | two.onDisconnect.addListener(shutdown) 75 | console.log('tab ' + id + ' connected.') 76 | updateContextMenuItem() 77 | } 78 | 79 | chrome.runtime.onMessage.addListener((req, sender) => { 80 | if (sender.tab && req.vueDetected) { 81 | const suffix = req.nuxtDetected ? '.nuxt' : '' 82 | 83 | chrome.browserAction.setIcon({ 84 | tabId: sender.tab.id, 85 | path: { 86 | 16: `icons/16${suffix}.png`, 87 | 48: `icons/48${suffix}.png`, 88 | 128: `icons/128${suffix}.png` 89 | } 90 | }) 91 | chrome.browserAction.setPopup({ 92 | tabId: sender.tab.id, 93 | popup: req.devtoolsEnabled ? `popups/enabled${suffix}.html` : `popups/disabled${suffix}.html` 94 | }) 95 | } 96 | }) 97 | 98 | // Right-click inspect context menu entry 99 | let activeTabId 100 | chrome.tabs.onActivated.addListener(({ tabId }) => { 101 | activeTabId = tabId 102 | updateContextMenuItem() 103 | }) 104 | 105 | function updateContextMenuItem () { 106 | chrome.contextMenus.removeAll(() => { 107 | if (ports[activeTabId]) { 108 | chrome.contextMenus.create({ 109 | id: 'vue-inspect-instance', 110 | title: 'Inspect Vue component', 111 | contexts: ['all'] 112 | }) 113 | } 114 | }) 115 | } 116 | 117 | chrome.contextMenus.onClicked.addListener((info, tab) => { 118 | chrome.runtime.sendMessage({ 119 | vueContextMenu: { 120 | id: info.menuItemId 121 | } 122 | }) 123 | }) 124 | -------------------------------------------------------------------------------- /.devTools/shell-chrome/src/devtools-background.js: -------------------------------------------------------------------------------- 1 | // This is the devtools script, which is called when the user opens the 2 | // Chrome devtool on a page. We check to see if we global hook has detected 3 | // Vue presence on the page. If yes, create the Vue panel; otherwise poll 4 | // for 10 seconds. 5 | 6 | let panelLoaded = false 7 | let panelShown = false 8 | let pendingAction 9 | let created = false 10 | let checkCount = 0 11 | 12 | chrome.devtools.network.onNavigated.addListener(createPanelIfHasVue) 13 | const checkVueInterval = setInterval(createPanelIfHasVue, 1000) 14 | createPanelIfHasVue() 15 | 16 | function createPanelIfHasVue () { 17 | if (created || checkCount++ > 10) { 18 | clearInterval(checkVueInterval) 19 | return 20 | } 21 | panelLoaded = false 22 | panelShown = false 23 | chrome.devtools.inspectedWindow.eval( 24 | '!!(window.__VUE_DEVTOOLS_GLOBAL_HOOK__.Vue)', 25 | function (hasVue) { 26 | if (!hasVue || created) { 27 | return 28 | } 29 | clearInterval(checkVueInterval) 30 | created = true 31 | chrome.devtools.panels.create( 32 | 'Vue', 'icons/128.png', 'devtools.html', 33 | panel => { 34 | // panel loaded 35 | panel.onShown.addListener(onPanelShown) 36 | panel.onHidden.addListener(onPanelHidden) 37 | } 38 | ) 39 | } 40 | ) 41 | } 42 | 43 | // Runtime messages 44 | 45 | chrome.runtime.onMessage.addListener(request => { 46 | if (request === 'vue-panel-load') { 47 | onPanelLoad() 48 | } else if (request.vueToast) { 49 | toast(request.vueToast.message, request.vueToast.type) 50 | } else if (request.vueContextMenu) { 51 | onContextMenu(request.vueContextMenu) 52 | } 53 | }) 54 | 55 | // Page context menu entry 56 | 57 | function onContextMenu ({ id }) { 58 | if (id === 'vue-inspect-instance') { 59 | const src = `window.__VUE_DEVTOOLS_CONTEXT_MENU_HAS_TARGET__` 60 | 61 | chrome.devtools.inspectedWindow.eval(src, function (res, err) { 62 | if (err) { 63 | console.log(err) 64 | } 65 | if (typeof res !== 'undefined' && res) { 66 | panelAction(() => { 67 | chrome.runtime.sendMessage('vue-get-context-menu-target') 68 | }, 'Open Vue devtools to see component details') 69 | } else { 70 | pendingAction = null 71 | toast('No Vue component was found', 'warn') 72 | } 73 | }) 74 | } 75 | } 76 | 77 | // Action that may execute immediatly 78 | // or later when the Vue panel is ready 79 | 80 | function panelAction (cb, message = null) { 81 | if (created && panelLoaded && panelShown) { 82 | cb() 83 | } else { 84 | pendingAction = cb 85 | message && toast(message) 86 | } 87 | } 88 | 89 | function executePendingAction () { 90 | pendingAction && pendingAction() 91 | pendingAction = null 92 | } 93 | 94 | // Execute pending action when Vue panel is ready 95 | 96 | function onPanelLoad () { 97 | executePendingAction() 98 | panelLoaded = true 99 | } 100 | 101 | // Manage panel visibility 102 | 103 | function onPanelShown () { 104 | chrome.runtime.sendMessage('vue-panel-shown') 105 | panelShown = true 106 | panelLoaded && executePendingAction() 107 | } 108 | 109 | function onPanelHidden () { 110 | chrome.runtime.sendMessage('vue-panel-hidden') 111 | panelShown = false 112 | } 113 | 114 | // Toasts 115 | 116 | function toast (message, type = 'normal') { 117 | const src = `(function() { 118 | __VUE_DEVTOOLS_TOAST__(\`${message}\`, '${type}'); 119 | })()` 120 | 121 | chrome.devtools.inspectedWindow.eval(src, function (res, err) { 122 | if (err) { 123 | console.log(err) 124 | } 125 | }) 126 | } 127 | -------------------------------------------------------------------------------- /src/pages/components/cimo.vue: -------------------------------------------------------------------------------- 1 |