From 2cc83296951261b7c6384275638bf87e8059beb4 Mon Sep 17 00:00:00 2001 From: sheng <905537351@qq.com> Date: Wed, 27 May 2026 18:07:48 +0800 Subject: [PATCH] refactor: remove old demo pages and static menu logic MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 删除大量旧的示例页面、组件示例和静态菜单配置 2. 新增菜单扁平数组转树形结构工具函数 3. 重构菜单加载逻辑,改为从后端动态获取并格式化 4. 新增全局权限检查方法和自定义权限指令 5. 优化侧边栏菜单路由跳转逻辑,自动跳转第一个有权限的子页面 6. 移除路由中对旧demo模块的引用 --- docs/menu-permission-migration.md | 601 ++++++++++ src/api/demo.js | 86 -- src/api/menu.js | 13 + .../header-aside/components/mixin/menu.js | 41 +- src/libs/util.js | 29 + src/main.js | 29 +- src/menu/index.js | 84 +- src/menu/modules/demo-components.js | 88 -- src/menu/modules/demo-playground.js | 133 --- src/menu/modules/demo-plugins.js | 29 - src/plugin/d2admin/index.js | 21 + src/router/modules/components.js | 41 - src/router/modules/playground.js | 47 - src/router/modules/plugins.js | 24 - src/router/modules/production-master-data.js | 18 - src/router/routes.js | 9 +- src/store/modules/d2admin/modules/menu.js | 92 +- src/views/demo/components/container/api.vue | 104 -- .../demo/components/container/card-bs.vue | 16 - .../demo/components/container/card-slot.vue | 16 - src/views/demo/components/container/card.vue | 14 - .../container/components/d2-demo-article.vue | 50 - .../demo/components/container/full-bs.vue | 16 - .../demo/components/container/full-slot.vue | 16 - src/views/demo/components/container/full.vue | 14 - .../demo/components/container/ghost-bs.vue | 20 - .../demo/components/container/ghost-slot.vue | 20 - src/views/demo/components/container/ghost.vue | 18 - .../demo/components/container/md/long.md | 53 - .../demo/components/container/md/short.md | 17 - src/views/demo/components/countup/index.vue | 94 -- .../demo/components/editor-quill/index.vue | 49 - .../demo/components/editor-quill/value.js | 6 - .../demo/components/editor-ueditor/index.vue | 33 - .../demo/components/highlight/code/css.js | 8 - .../demo/components/highlight/code/html.js | 8 - .../components/highlight/code/javascript.js | 3 - .../demo/components/highlight/code/scss.js | 8 - src/views/demo/components/highlight/index.vue | 38 - .../icon/components/d2-icon-cell.vue | 82 -- src/views/demo/components/icon/data/index.js | 1004 ----------------- src/views/demo/components/icon/icon-svg.vue | 42 - src/views/demo/components/icon/icon.vue | 22 - src/views/demo/components/icon/list.vue | 46 - src/views/demo/components/icon/select-svg.vue | 24 - src/views/demo/components/icon/select.vue | 56 - src/views/demo/components/index/index.vue | 21 - src/views/demo/components/json-tree/index.vue | 24 - src/views/demo/components/layout/grid.vue | 122 -- .../demo/components/layout/splitpane.vue | 37 - src/views/demo/components/markdown/md/doc.md | 38 - src/views/demo/components/markdown/source.vue | 17 - src/views/demo/components/markdown/url.vue | 6 - .../playground/add-routes/alternates/1.vue | 5 - .../playground/add-routes/alternates/2.vue | 5 - .../playground/add-routes/alternates/3.vue | 5 - .../demo/playground/add-routes/routes.vue | 109 -- src/views/demo/playground/db/all/index.vue | 33 - .../demo/playground/db/page-public/index.vue | 127 --- .../db/page-snapshot-public/index.vue | 114 -- .../db/page-snapshot-user/index.vue | 114 -- .../demo/playground/db/page-user/index.vue | 139 --- src/views/demo/playground/db/public/index.vue | 123 -- src/views/demo/playground/db/user/index.vue | 125 -- src/views/demo/playground/env/index.vue | 16 - .../demo/playground/frame/d2-doc/index.vue | 3 - .../demo/playground/frame/html/index.vue | 3 - .../demo/playground/frame/report/index.vue | 3 - src/views/demo/playground/index/index.vue | 21 - src/views/demo/playground/locales/index.vue | 22 - src/views/demo/playground/log/ajax/index.vue | 20 - .../playground/log/console/image/demo.png | Bin 66362 -> 0 bytes .../demo/playground/log/console/index.vue | 67 -- src/views/demo/playground/log/error/index.vue | 18 - src/views/demo/playground/log/log/index.vue | 28 - src/views/demo/playground/page-argu/get.vue | 16 - src/views/demo/playground/page-argu/send.vue | 55 - src/views/demo/playground/page-cache/off.vue | 17 - src/views/demo/playground/page-cache/on.vue | 18 - .../demo/playground/page-cache/params.vue | 42 - .../playground/store/fullscreen/index.vue | 19 - .../demo/playground/store/gray/index.vue | 87 -- .../demo/playground/store/menu/index.vue | 148 --- .../demo/playground/store/page/index.vue | 98 -- .../demo/playground/store/size/index.vue | 39 - .../demo/playground/store/theme/index.vue | 74 -- .../playground/store/transition/index.vue | 26 - src/views/demo/playground/store/ua/index.vue | 23 - .../demo/plugins/clipboard-polyfill/index.vue | 82 -- src/views/demo/plugins/day/index.vue | 73 -- src/views/demo/plugins/export/table.vue | 72 -- src/views/demo/plugins/export/txt.vue | 47 - src/views/demo/plugins/import/csv.vue | 62 - src/views/demo/plugins/import/xlsx.vue | 64 -- src/views/demo/plugins/index/index.vue | 21 - src/views/demo/plugins/js-cookie/index.vue | 54 - 96 files changed, 799 insertions(+), 4985 deletions(-) create mode 100644 docs/menu-permission-migration.md delete mode 100644 src/api/demo.js create mode 100644 src/api/menu.js delete mode 100644 src/menu/modules/demo-components.js delete mode 100644 src/menu/modules/demo-playground.js delete mode 100644 src/menu/modules/demo-plugins.js delete mode 100644 src/router/modules/components.js delete mode 100644 src/router/modules/playground.js delete mode 100644 src/router/modules/plugins.js delete mode 100644 src/router/modules/production-master-data.js delete mode 100644 src/views/demo/components/container/api.vue delete mode 100644 src/views/demo/components/container/card-bs.vue delete mode 100644 src/views/demo/components/container/card-slot.vue delete mode 100644 src/views/demo/components/container/card.vue delete mode 100644 src/views/demo/components/container/components/d2-demo-article.vue delete mode 100644 src/views/demo/components/container/full-bs.vue delete mode 100644 src/views/demo/components/container/full-slot.vue delete mode 100644 src/views/demo/components/container/full.vue delete mode 100644 src/views/demo/components/container/ghost-bs.vue delete mode 100644 src/views/demo/components/container/ghost-slot.vue delete mode 100644 src/views/demo/components/container/ghost.vue delete mode 100644 src/views/demo/components/container/md/long.md delete mode 100644 src/views/demo/components/container/md/short.md delete mode 100644 src/views/demo/components/countup/index.vue delete mode 100644 src/views/demo/components/editor-quill/index.vue delete mode 100644 src/views/demo/components/editor-quill/value.js delete mode 100644 src/views/demo/components/editor-ueditor/index.vue delete mode 100644 src/views/demo/components/highlight/code/css.js delete mode 100644 src/views/demo/components/highlight/code/html.js delete mode 100644 src/views/demo/components/highlight/code/javascript.js delete mode 100644 src/views/demo/components/highlight/code/scss.js delete mode 100644 src/views/demo/components/highlight/index.vue delete mode 100644 src/views/demo/components/icon/components/d2-icon-cell.vue delete mode 100644 src/views/demo/components/icon/data/index.js delete mode 100644 src/views/demo/components/icon/icon-svg.vue delete mode 100644 src/views/demo/components/icon/icon.vue delete mode 100644 src/views/demo/components/icon/list.vue delete mode 100644 src/views/demo/components/icon/select-svg.vue delete mode 100644 src/views/demo/components/icon/select.vue delete mode 100644 src/views/demo/components/index/index.vue delete mode 100644 src/views/demo/components/json-tree/index.vue delete mode 100644 src/views/demo/components/layout/grid.vue delete mode 100644 src/views/demo/components/layout/splitpane.vue delete mode 100644 src/views/demo/components/markdown/md/doc.md delete mode 100644 src/views/demo/components/markdown/source.vue delete mode 100644 src/views/demo/components/markdown/url.vue delete mode 100644 src/views/demo/playground/add-routes/alternates/1.vue delete mode 100644 src/views/demo/playground/add-routes/alternates/2.vue delete mode 100644 src/views/demo/playground/add-routes/alternates/3.vue delete mode 100644 src/views/demo/playground/add-routes/routes.vue delete mode 100644 src/views/demo/playground/db/all/index.vue delete mode 100644 src/views/demo/playground/db/page-public/index.vue delete mode 100644 src/views/demo/playground/db/page-snapshot-public/index.vue delete mode 100644 src/views/demo/playground/db/page-snapshot-user/index.vue delete mode 100644 src/views/demo/playground/db/page-user/index.vue delete mode 100644 src/views/demo/playground/db/public/index.vue delete mode 100644 src/views/demo/playground/db/user/index.vue delete mode 100644 src/views/demo/playground/env/index.vue delete mode 100644 src/views/demo/playground/frame/d2-doc/index.vue delete mode 100644 src/views/demo/playground/frame/html/index.vue delete mode 100644 src/views/demo/playground/frame/report/index.vue delete mode 100644 src/views/demo/playground/index/index.vue delete mode 100644 src/views/demo/playground/locales/index.vue delete mode 100644 src/views/demo/playground/log/ajax/index.vue delete mode 100644 src/views/demo/playground/log/console/image/demo.png delete mode 100644 src/views/demo/playground/log/console/index.vue delete mode 100644 src/views/demo/playground/log/error/index.vue delete mode 100644 src/views/demo/playground/log/log/index.vue delete mode 100644 src/views/demo/playground/page-argu/get.vue delete mode 100644 src/views/demo/playground/page-argu/send.vue delete mode 100644 src/views/demo/playground/page-cache/off.vue delete mode 100644 src/views/demo/playground/page-cache/on.vue delete mode 100644 src/views/demo/playground/page-cache/params.vue delete mode 100644 src/views/demo/playground/store/fullscreen/index.vue delete mode 100644 src/views/demo/playground/store/gray/index.vue delete mode 100644 src/views/demo/playground/store/menu/index.vue delete mode 100644 src/views/demo/playground/store/page/index.vue delete mode 100644 src/views/demo/playground/store/size/index.vue delete mode 100644 src/views/demo/playground/store/theme/index.vue delete mode 100644 src/views/demo/playground/store/transition/index.vue delete mode 100644 src/views/demo/playground/store/ua/index.vue delete mode 100644 src/views/demo/plugins/clipboard-polyfill/index.vue delete mode 100644 src/views/demo/plugins/day/index.vue delete mode 100644 src/views/demo/plugins/export/table.vue delete mode 100644 src/views/demo/plugins/export/txt.vue delete mode 100644 src/views/demo/plugins/import/csv.vue delete mode 100644 src/views/demo/plugins/import/xlsx.vue delete mode 100644 src/views/demo/plugins/index/index.vue delete mode 100644 src/views/demo/plugins/js-cookie/index.vue diff --git a/docs/menu-permission-migration.md b/docs/menu-permission-migration.md new file mode 100644 index 00000000..b44b2b8d --- /dev/null +++ b/docs/menu-permission-migration.md @@ -0,0 +1,601 @@ +# Menu 权限迁移方案 + +> 参照项目:`D:\code\company\SCTMES_MES_V5\vue-app`(以下简称"源项目") + +--- + +## 一、源项目(SCTMES)Menu 权限架构 + +### 1.1 后端接口 + +``` +GET system_settings/menu_configuration/menu/all +``` + +API 文件:[src/api/system_settings/menu_configuration/menu.js](file:///D:\code\company\SCTMES_MES_V5\vue-app\src\api\system_settings\menu_configuration\menu.js) + +返回当前用户可见的**扁平数组**,字段如下: + +| 字段 | 类型 | 说明 | +|------|------|------| +| `menu_id` | number | 主键,用于构建父子关系 | +| `parent_id` | number | 父节点 ID,`0` 表示顶栏根节点 | +| `url` | string | 前端路由路径,如 `/system_settings/user_management/user` | +| `name` | string | 菜单显示名称 | +| `icon` | string | 图标名(FontAwesome) | +| `is_navi` | number | 是否作为导航菜单展示(1=是) | +| `status` | number | 启用/禁用 | +| `type` | string | 菜单类型 | +| `params` | string | 额外参数 | +| `sort` | number | 排序 | +| `remark` | string | 备注 | + +### 1.2 菜单数据全链路 + +``` +登录成功 → account.login() → dispatch('load') + │ + ▼ + account.load() + │ + ...加载 user/theme/transition/page/menu/size/color... + │ + ▼ + dispatch('d2admin/menu/sourceDataLoad') + │ + ┌────────────┴────────────┐ + │ │ + localStorage localStorage 为空 + 有缓存 且有 token + │ │ + ▼ ▼ + 直接读缓存 GET /menu/all 后端接口 + │ + ▼ + 写入 localStorage 缓存 + │ + └────────────┬────────────┘ + │ + ▼ + menu.install(this, sourceData) +``` + +**Store 文件**:[src/store/modules/d2admin/modules/menu.js](file:///D:\code\company\SCTMES_MES_V5\vue-app\src\store\modules\d2admin\modules\menu.js) + +```js +state: { + header: [], + aside: [], + asideCollapse: setting.menu.asideCollapse, + asideTransition: setting.menu.asideTransition, + authKey: {}, // ← 权限字典 { '/path': '菜单名', ... } + sourceData: [] // ← 菜单源数据(来自后端或本地缓存) +} +``` + +### 1.3 `sourceDataLoad` action 核心逻辑 + +```js +async sourceDataLoad({ state, dispatch }) { + // 1. 优先从 localStorage 读取缓存 + state.sourceData = await dispatch('d2admin/db/get', { + dbName: 'database', + path: '$menu.sourceData', + defaultValue: [], + user: true + }, { root: true }) + + // 2. 缓存为空且已登录 → 调后端获取 + if (!state.sourceData.length && util.cookies.get('token')) { + const res = await getMenuAll(null) + state.sourceData = res.data || [] + await dispatch('d2admin/db/set', { + dbName: 'database', + path: '$menu.sourceData', + value: state.sourceData, + user: true + }, { root: true }) + } + + // 3. 处理为 header/aside/authKey + menu.install(this, state.sourceData) +} +``` + +### 1.4 `menu.install()` — 扁平数据 → 菜单树 + 权限字典 + +**文件**:[src/menu/index.js](file:///D:\code\company\SCTMES_MES_V5\vue-app\src\menu\index.js) + +```js +export default { + install(vm, source) { + // 1. 构建权限字典 { '/path': '菜单名' } + vm.commit('d2admin/menu/headerAuth', source) + + // 2. 扁平数据转为 {header: [], aside: []} 树结构 + const { header, aside } = getMenuData(source) + + // 3. 写入 store → 触发菜单渲染 + vm.commit('d2admin/menu/headerSet', header) + vm.commit('d2admin/menu/asideSet', aside) + } +} +``` + +`getMenuData()` 核心流程: + +``` +source (扁平数组) + │ + ├── 过滤: is_navi !== 1 的跳过 + │ + ├── parent_id === 0 → 推入 header[] + │ + └── 全部节点 → 推入 aside[] + │ + ▼ + util.formatDataToTree(aside) { menu_id ↔ parent_id } + │ + ▼ + 树形结构 aside +``` + +**`headerAuth` mutation**:遍历 `source`,将每个有 `url` 的节点写入 `authKey[url] = name`: + +```js +headerAuth(state, source) { + let auth = {} + source.forEach(value => { + if (value.url) { + auth[value.url] = value.name + } + }) + state.authKey = auth +} +``` + +### 1.5 权限控制系统 + +**`$permission()` 方法** — 定义在 [src/plugin/d2admin/index.js](file:///D:\code\company\SCTMES_MES_V5\vue-app\src\plugin\d2admin\index.js#L50): + +```js +Vue.prototype.$permission = (value, type = 'menu') => { + let path = '' + const auth = store.state.d2admin.menu.authKey + + switch (type) { + case 'menu': // 直接用 URL 查 + path = value + break + case 'router': // 路由 name → URL + path = value.name.replace(/-/g, '/') + path.slice(0, 1) !== '/' && (path = '/' + path) + break + } + + return !!(path && Object.prototype.hasOwnProperty.call(auth, path)) +} +``` + +**`v-permission` 指令** — 定义在 [src/main.js](file:///D:\code\company\SCTMES_MES_V5\vue-app\src\main.js#L72-L78): + +```js +Vue.directive('permission', { + bind: (el, binding) => { + if (!Vue.prototype.$permission(binding.value)) { + el.parentNode ? el.parentNode.removeChild(el) : el.style.display = 'none' + } + } +}) +``` + +使用示例: +```html +新增用户 +``` + +### 1.6 菜单导航权限过滤 + +**Menu Mixin** — [src/layout/header-aside/components/mixin/menu.js](file:///D:\code\company\SCTMES_MES_V5\vue-app\src\layout\header-aside\components\mixin\menu.js): + +点击顶栏一级菜单时,不直接跳转,而是查找第一个有权限的子路由: + +```js +getRouterAuthPath(index, indexPath) { + // 子路由直接访问 + if (index === '/index' || !indexPath || indexPath.length > 1) { + this.$router.push({ path: index }) + return + } + + // 查找一级路由下第一个有权限的子路由 + let router = null + for (const value of frameInRoutes) { + if (value.path === index) { + router = value.children + break + } + } + + if (!router) { + this.$router.push({ path: index }) + return + } + + for (const value of router) { + const newPath = index + '/' + value.path + if (this.$permission(newPath)) { + this.$router.push({ path: newPath }) + break + } + } +} +``` + +### 1.7 路由 — 全部静态注册 + +路由在 [src/router/routes.js](file:///D:\code\company\SCTMES_MES_V5\vue-app\src\router\routes.js) 中**全部静态定义**,不使用 `addRoute`。 + +路由守卫([src/router/index.js](file:///D:\code\company\SCTMES_MES_V5\vue-app\src\router\index.js))仅判断 token 是否存在,不校验具体路由权限。权限控制在**菜单渲染**和**菜单点击时**完成。 + +### 1.8 main.js 启动流程 + +[src/main.js](file:///D:\code\company\SCTMES_MES_V5\vue-app\src\main.js#L108-L137) + +```js +created() { + // 仅初始化页面池,不再设置静态菜单 + this.$store.commit('d2admin/page/init', frameInRoutes) + // 静态菜单设置已注释: + // this.$store.commit('d2admin/menu/headerSet', menuHeader) + // this.$store.commit('d2admin/search/init', menuHeader) +}, +mounted() { + this.$store.dispatch('d2admin/account/load') // → sourceDataLoad → 获取菜单 +}, +watch: { + // $route.matched 切换侧边栏的 watch 已注释 +} +``` + +--- + +## 二、mes-ui 当前现状 vs 目标 + +| 模块 | mes-ui 现状 | 源项目(目标) | +|------|-----------|---------------| +| 菜单数据来源 | `src/menu/modules/*.js` 静态硬编码 | 后端 `GET /menu/all` + localStorage 缓存 | +| `sourceDataLoad` | 仅 localStorage 读取,不参与菜单构建 | localStorage 兜底 + 调后端 → `menu.install()` | +| 权限字典 | 无 | `authKey: { '/path': 'name' }` | +| 菜单树构建 | 编译时 `supplementPath()` | 运行时 `getMenuData()` + `formatDataToTree()` | +| 权限检查 | 无 | `$permission()` + `v-permission` 指令 | +| 菜单点击 | 直接 `$router.push` | `getRouterAuthPath()` 查找首个有权限子路由 | +| main.js 菜单初始化 | `created` 中 `headerSet(menuHeader)` | 注释掉静态菜单,由 `mounted` 中的 `load()` 触发 | +| 路由注册 | 全部静态 | 全部静态(一致) | +| 路由守卫 | 仅 token 检查 | 仅 token 检查(一致) | + +--- + +## 三、迁移计划 + +### 阶段 1️⃣:约定后端接口格式 + +后端接口:`GET /api/menu/all`(或复用源项目的 `system_settings/menu_configuration/menu/all`) + +返回格式(扁平数组): + +```json +{ + "code": 0, + "data": [ + { "menu_id": 1, "parent_id": 0, "url": "/index", "name": "首页", "icon": "home", "is_navi": 1 }, + { "menu_id": 2, "parent_id": 0, "url": "/production_master_data", "name": "生产主数据", "icon": "cogs", "is_navi": 1 }, + { "menu_id": 3, "parent_id": 2, "url": "/production_master_data/factory_model/factory_area", "name": "工厂区域", "icon": "map-marker", "is_navi": 1 } + ] +} +``` + +### 阶段 2️⃣:新增/改造 API 层 + +**新增** `src/api/menu.js`(参照源项目 [menu.js](file:///D:\code\company\SCTMES_MES_V5\vue-app\src\api\system_settings\menu_configuration\menu.js)): + +```js +import { request } from '@/api/_service' + +export function getMenuAll(data) { + return request({ + url: 'menu/all', + method: 'get', + params: { + method: 'system_settings_menu_configuration_menu_all', + platform: 'background', + ...data + } + }) +} +``` + +### 阶段 3️⃣:改造 `menu.js` Store + +**改造** [src/store/modules/d2admin/modules/menu.js](file:///d:\code\mes\mes-ui\src\store\modules\d2admin\modules\menu.js) + +| 改动 | 内容 | +|------|------| +| state | 新增 `authKey: {}` | +| `sourceDataLoad` action | 改为:localStorage 兜底 → 调后端 → `menu.install()` | +| mutations | 新增 `headerAuth(state, source)` → 构建 `authKey` 字典 | + +```js +// 关键变更 — sourceDataLoad: +async sourceDataLoad({ state, commit, dispatch }) { + // 1. 先读 localStorage 缓存 + state.sourceData = await dispatch('d2admin/db/get', { + dbName: 'database', + path: '$menu.sourceData', + defaultValue: [], + user: true + }, { root: true }) + + // 2. 缓存为空且已登录 → 调后端 + if (!state.sourceData.length && util.cookies.get('token')) { + const res = await getMenuAll() + state.sourceData = res || [] + await dispatch('d2admin/db/set', { + dbName: 'database', + path: '$menu.sourceData', + value: state.sourceData, + user: true + }, { root: true }) + } + + // 3. 构建菜单树 + 权限字典 + menuUtil.install(this, state.sourceData) +} +``` + +### 阶段 4️⃣:改造 `src/menu/index.js` — 从静态导出变为工具模块 + +将 [src/menu/index.js](file:///d:\code\mes\mes-ui\src\menu\index.js) 从"导出静态菜单配置"改为"菜单处理工具"(参照源项目): + +```js +import util from '@/libs/util' + +function getMenuData(arr) { + let tree = { header: [], aside: [] } + + arr.forEach(value => { + if (!value.is_navi) return // 过滤非导航菜单 + + const menuItem = { + path: value.url, + title: value.name, + icon: value.icon, + type: value.type, + params: value.params + } + + if (value.parent_id === 0) { + tree.header.push({ ...menuItem }) + } + + menuItem.menu_id = value.menu_id + menuItem.parent_id = value.parent_id + tree.aside.push(menuItem) + }) + + // 扁平数组转树 + tree.aside = util.formatDataToTree(tree.aside) + return tree +} + +export default { + install(vm, source) { + vm.commit('d2admin/menu/headerAuth', source) + const { header, aside } = getMenuData(source) + vm.commit('d2admin/menu/headerSet', header) + vm.commit('d2admin/menu/asideSet', aside) + } +} +``` + +原有的静态菜单模块(`src/menu/modules/demo-*.js`)可保留但不再被引用,后续按需清理。 + +### 阶段 5️⃣:增加权限控制基础设施 + +#### 5.1 `$permission` 方法 + +**改造** `src/plugin/d2admin/index.js`,新增: + +```js +Vue.prototype.$permission = (value, type = 'menu') => { + let path = '' + const auth = store.state.d2admin.menu.authKey + + switch (type) { + case 'menu': + path = value + break + case 'router': + path = value.name.replace(/-/g, '/') + path.slice(0, 1) !== '/' && (path = '/' + path) + break + } + + return !!(path && Object.prototype.hasOwnProperty.call(auth, path)) +} +``` + +#### 5.2 `v-permission` 指令 + +**改造** `src/main.js`,新增: + +```js +Vue.directive('permission', { + bind: (el, binding) => { + if (!Vue.prototype.$permission(binding.value)) { + el.parentNode ? el.parentNode.removeChild(el) : el.style.display = 'none' + } + } +}) +``` + +#### 5.3 菜单点击权限过滤 + +**改造** [src/layout/header-aside/components/mixin/menu.js](file:///d:\code\mes\mes-ui\src\layout\header-aside\components\mixin\menu.js),增加 `getRouterAuthPath` 方法: + +```js +import { frameInRoutes } from '@/router/routes' + +methods: { + handleMenuSelect(index, indexPath) { + if (/^d2-menu-empty-\d+$/.test(index) || index === undefined) { + this.$message.warning('临时菜单') + } else if (/^https:\/\/|http:\/\//.test(index)) { + util.open(index) + } else { + this.getRouterAuthPath(index, indexPath) + } + }, + + getRouterAuthPath(index, indexPath) { + if (index === '/index' || !indexPath || indexPath.length > 1) { + this.$router.push({ path: index }) + return + } + + let router = null + for (const value of frameInRoutes) { + if (value.path === index) { + router = value.children + break + } + } + + if (!router) { + this.$router.push({ path: index }) + return + } + + for (const value of router) { + const newPath = index + '/' + value.path + if (this.$permission(newPath)) { + this.$router.push({ path: newPath }) + break + } + } + } +} +``` + +### 阶段 6️⃣:改造 `main.js` 启动流程 + +**改造** [src/main.js](file:///d:\code\mes\mes-ui\src\main.js): + +```js +created() { + this.$store.commit('d2admin/page/init', frameInRoutes) + // 注释掉静态菜单设置: + // this.$store.commit('d2admin/menu/headerSet', menuHeader) + // this.$store.commit('d2admin/search/init', menuHeader) +}, +mounted() { + this.$store.commit('d2admin/releases/versionShow') + this.$store.dispatch('d2admin/account/load') // → sourceDataLoad → 获取后端菜单 + this.$store.commit('d2admin/ua/get') + this.$store.dispatch('d2admin/fullscreen/listen') +}, +watch: { + // 注释掉 $route.matched 侧边栏切换(由 store.aside 直接驱动) + // '$route.matched': { ... } +} +``` + +### 阶段 7️⃣:增加 `util.formatDataToTree` 工具函数 + +**改造** `src/libs/util.js`,新增: + +```js +util.formatDataToTree = (data, key = 'menu_id', pid = 'parent_id') => { + if (!data || data.length <= 0) return [] + + let map = {} + data.forEach(value => { map[value[key]] = { ...value } }) + + let tree = [] + data.forEach(item => { + const id = item[key] + if (map[id][pid] && map[map[id][pid]]) { + if (!map[map[id][pid]].children) { + map[map[id][pid]].children = [] + } + map[map[id][pid]].children.push(map[id]) + } else { + tree.push(map[id]) + } + }) + return tree +} +``` + +--- + +## 四、影响的文件清单 + +| 文件 | 改动类型 | 说明 | +|------|----------|------| +| `src/api/menu.js` | **新增** | 菜单 API(`getMenuAll`) | +| `src/store/modules/d2admin/modules/menu.js` | **改造** | `sourceDataLoad` 加后端调用 + `headerAuth` mutation + `authKey` state | +| `src/menu/index.js` | **重写** | 从静态配置改为 `install()` 工具模块 | +| `src/plugin/d2admin/index.js` | **改造** | 新增 `$permission` 方法 | +| `src/main.js` | **改造** | 注释静态菜单设置;新增 `v-permission` 指令 | +| `src/layout/header-aside/components/mixin/menu.js` | **改造** | 增加 `getRouterAuthPath` 权限过滤 | +| `src/libs/util.js` | **改造** | 新增 `formatDataToTree` 工具函数 | +| `src/menu/modules/demo-*.js` | **后续可删** | 静态菜单数据不再使用,单独清理 | + +--- + +## 五、完整时序图 + +``` + 用户登录 + │ + ▼ + login/index.vue → dispatch('d2admin/account/login') + │ + ▼ + account.js login action + ├── loginAdminUser() → 后端登录接口 + ├── util.cookies.set() → 存 token/uuid + ├── dispatch('d2admin/user/set') → 存用户信息 + └── dispatch('load') + │ + ├── d2admin/user/load → 加载用户名 + ├── d2admin/theme/load → 加载主题 + ├── d2admin/transition/load → 加载过渡效果 + ├── d2admin/page/openedLoad → 加载标签页 + ├── d2admin/menu/asideLoad → 加载侧边栏收起设置 + ├── d2admin/size/load → 加载全局尺寸 + ├── d2admin/color/load → 加载颜色设置 + └── d2admin/menu/sourceDataLoad + │ + ├── 先读 localStorage 缓存 + ├── 缓存空 → GET /api/menu/all 后端接口 + ├── 写入 localStorage 缓存 + └── menu.install(this, sourceData) + ├── headerAuth → 构建 authKey 权限字典 + ├── getMenuData → 扁平 → {header, aside} 树 + ├── headerSet → 顶栏菜单渲染 + └── asideSet → 侧边栏菜单渲染 + │ + ▼ + 跳转到首页 → 菜单已按权限渲染 +``` + +--- + +## 六、注意事项 + +1. **路由仍是静态注册的**:mes-ui 不需要改造成动态 `addRoute`,路由全部在 `router/routes.js` 中静态定义即可,权限通过菜单显示/隐藏 + `getRouterAuthPath` 控制。 +2. **不要删除源项目代码**:源项目在 `D:\code\company\SCTMES_MES_V5\vue-app`,仅作为参照,不对其做任何修改。 +3. **localStorage 缓存**是离线兜底:首次登录调后端,后续从缓存读取;注销时清空缓存。 +4. **`block` cookie**:已在登录页 `mounted` 中设为 `'false'`,注销时设为 `'true'`,用于控制错误日志是否弹出提示。 diff --git a/src/api/demo.js b/src/api/demo.js deleted file mode 100644 index ad10d27a..00000000 --- a/src/api/demo.js +++ /dev/null @@ -1,86 +0,0 @@ -import { find, map, random } from 'lodash' -import faker from 'faker/locale/zh_CN' -import { requestForMock, mock } from '@/api/_service.js' -import * as tools from '@/api/_tools.js' - -const db = [ - { id: '1', name: '用户 1', address: '上海市普陀区金沙江路 1518 弄' }, - { id: '2', name: '用户 2', address: '上海市普陀区金沙江路 1517 弄' }, - { id: '3', name: '用户 3', address: '上海市普陀区金沙江路 1519 弄' }, - { id: '4', name: '用户 4', address: '上海市普陀区金沙江路 1516 弄' } -] - -/** - * @description 列表 - */ -export function DEMO_MOCK_LIST () { - // 模拟数据 - mock - .onAny('/demo/business/issues/142/fetch') - .reply(...tools.responseSuccess({ list: db })) - // 接口请求 - return requestForMock({ - url: '/demo/business/issues/142/fetch', - method: 'get' - }) -} - -/** - * @description 详情 - * @param {String} id 项目 ID - */ -export function DEMO_MOCK_DETAIL (id) { - // 模拟数据 - mock - .onAny('/demo/business/issues/142/detail') - .reply(config => tools.responseSuccess(find(db, { id: config.params.id }))) - // 接口请求 - return requestForMock({ - url: '/demo/business/issues/142/detail', - method: 'get', - params: { - id - } - }) -} - -/** - * @description 列表 - */ -export function DEMO_MOCK_LIST2 (params = {}) { - // 模拟数据 - mock - .onAny('/demo/business/table/1/fetch') - .reply(config => tools.responseSuccess({ - page: { - total: 1000 - }, - list: map(Array(config.params.pageSize), () => ({ - key: faker.random.uuid(), - value: [10, 100, 200, 500][random(0, 3)], - type: faker.random.boolean(), - admin: faker.name.firstName() + faker.name.lastName(), - adminNote: faker.random.words(), - dateTimeCreat: faker.date.past(), - used: faker.random.boolean(), - dateTimeUse: faker.date.past() - })) - })) - // 接口请求 - return requestForMock({ - url: '/demo/business/table/1/fetch', - method: 'get', - params - }) -} - -/** - * @description 错误日志示例 请求一个不存在的地址 - */ -export function DEMO_LOG_AJAX () { - // 接口请求 - return requestForMock({ - url: '/invalid-url', - method: 'get' - }) -} diff --git a/src/api/menu.js b/src/api/menu.js new file mode 100644 index 00000000..955c1195 --- /dev/null +++ b/src/api/menu.js @@ -0,0 +1,13 @@ +import { request } from '@/api/_service' + +const urls = 'system_settings/menu_configuration/menu/' + +export function getMenuAll (data) { + return request({ + url: urls + 'all', + method: 'get', + params: { + ...data + } + }) +} diff --git a/src/layout/header-aside/components/mixin/menu.js b/src/layout/header-aside/components/mixin/menu.js index 7160b58f..8ed3a1d1 100644 --- a/src/layout/header-aside/components/mixin/menu.js +++ b/src/layout/header-aside/components/mixin/menu.js @@ -1,4 +1,5 @@ import util from '@/libs/util.js' +import { frameInRoutes } from '@/router/routes' export default { methods: { @@ -8,9 +9,43 @@ export default { } else if (/^https:\/\/|http:\/\//.test(index)) { util.open(index) } else { - this.$router.push({ - path: index - }) + this.getRouterAuthPath(index, indexPath) + } + }, + /** + * 点击菜单时进行权限过滤,查找第一个有权限的子路由 + * @param {String} index 选中菜单项的 index (path) + * @param {Array} indexPath 选中菜单项的 index path + */ + getRouterAuthPath (index, indexPath) { + // 首页或子级路由直接访问 + if (index === '/index' || !indexPath || indexPath.length > 1) { + this.$router.push({ path: index }) + return + } + + // 查找一级路由下是否存在子路由 + let router = null + for (const value of frameInRoutes) { + if (value.path === index) { + router = value.children + break + } + } + + // 不存在子路由则直接进入 + if (!router) { + this.$router.push({ path: index }) + return + } + + // 存在子路由时,跳转第一个有权限的子页面 + for (const value of router) { + const newPath = index + '/' + value.path + if (this.$permission(newPath)) { + this.$router.push({ path: newPath }) + break + } } } } diff --git a/src/libs/util.js b/src/libs/util.js index 9711c6a9..e7dba3fe 100644 --- a/src/libs/util.js +++ b/src/libs/util.js @@ -8,6 +8,35 @@ const util = { log } +/** + * 扁平数组转树形结构 + * @param {Array} data 扁平数组 + * @param {String} key 主键字段名 + * @param {String} pid 父节点字段名 + */ +util.formatDataToTree = (data, key = 'menu_id', pid = 'parent_id') => { + if (!data || data.length <= 0) { + return [] + } + + const map = {} + data.forEach(value => { map[value[key]] = { ...value } }) + + const tree = [] + data.forEach(item => { + const id = item[key] + if (map[id][pid] && map[map[id][pid]]) { + if (!map[map[id][pid]].children) { + map[map[id][pid]].children = [] + } + map[map[id][pid]].children.push(map[id]) + } else { + tree.push(map[id]) + } + }) + return tree +} + /** * @description 更新标题 * @param {String} title 标题 diff --git a/src/main.js b/src/main.js index d6d65b41..8802faa1 100644 --- a/src/main.js +++ b/src/main.js @@ -9,12 +9,20 @@ import store from '@/store/index' // 菜单和路由设置 import router from './router' -import { menuHeader, menuAside } from '@/menu' import { frameInRoutes } from '@/router/routes' // 核心插件 Vue.use(d2Admin) +// 权限控制指令 +Vue.directive('permission', { + bind: (el, binding) => { + if (!Vue.prototype.$permission(binding.value)) { + el.parentNode ? el.parentNode.removeChild(el) : el.style.display = 'none' + } + } +}) + new Vue({ router, store, @@ -23,31 +31,16 @@ new Vue({ created () { // 处理路由 得到每一级的路由设置 this.$store.commit('d2admin/page/init', frameInRoutes) - // 设置顶栏菜单 - this.$store.commit('d2admin/menu/headerSet', menuHeader) - // 初始化菜单搜索功能 - this.$store.commit('d2admin/search/init', menuHeader) + // 静态菜单和搜索由 account.load → sourceDataLoad 从后端动态加载 }, mounted () { // 展示系统信息 this.$store.commit('d2admin/releases/versionShow') - // 用户登录后从数据库加载一系列的设置 + // 用户登录后从数据库加载一系列的设置(含菜单) this.$store.dispatch('d2admin/account/load') // 获取并记录用户 UA this.$store.commit('d2admin/ua/get') // 初始化全屏监听 this.$store.dispatch('d2admin/fullscreen/listen') - }, - watch: { - // 检测路由变化切换侧边栏内容 - '$route.matched': { - handler (matched) { - if (matched.length > 0) { - const _side = menuAside.filter(menu => menu.path === matched[0].path) - this.$store.commit('d2admin/menu/asideSet', _side.length > 0 ? _side[0].children : []) - } - }, - immediate: true - } } }).$mount('#app') diff --git a/src/menu/index.js b/src/menu/index.js index ccbe36e1..0cee7b17 100644 --- a/src/menu/index.js +++ b/src/menu/index.js @@ -1,42 +1,52 @@ -import { uniqueId } from 'lodash' - -// 插件 -import demoPlugins from './modules/demo-plugins' -// 组件 -import demoComponents from './modules/demo-components' -// 功能 -import demoPlayground from './modules/demo-playground' +import util from '@/libs/util' /** - * @description 给菜单数据补充上 path 字段 - * @description https://github.com/d2-projects/d2-admin/issues/209 - * @param {Array} menu 原始的菜单数据 + * 将后端返回的扁平菜单数组转为 { header: [], aside: [] } 树结构 + * @param {Array} arr 后端返回的扁平菜单数据 */ -function supplementPath (menu) { - return menu.map(e => ({ - ...e, - path: e.path || uniqueId('d2-menu-empty-'), - ...e.children ? { - children: supplementPath(e.children) - } : {} - })) +function getMenuData (arr) { + const tree = { header: [], aside: [] } + + arr.forEach(value => { + if (!value.is_navi) { + return + } + + const menuItem = { + path: value.url, + title: value.name, + icon: value.icon, + type: value.type, + params: value.params + } + + // parent_id 为 0 的节点放入顶栏 + if (value.parent_id === 0) { + tree.header.push({ ...menuItem }) + } + + // 所有节点保留 menu_id / parent_id 用于构建侧栏树形结构 + menuItem.menu_id = value.menu_id + menuItem.parent_id = value.parent_id + tree.aside.push(menuItem) + }) + + // 扁平 aside 数组转为嵌套树 + tree.aside = util.formatDataToTree(tree.aside) + + return tree } -// 菜单 侧边栏 -export const menuAside = supplementPath([ - demoComponents, - demoPlugins, - demoPlayground -]) - -// 菜单 顶栏 -export const menuHeader = supplementPath([ - { - path: '/index', - title: '首页', - icon: 'home' - }, - demoPlayground, - demoComponents, - demoPlugins -]) +export default { + /** + * 由 sourceDataLoad 调用,将菜单源数据写入 store + * @param {Object} vm vuex store 实例 (this) + * @param {Array} source 后端返回的扁平菜单数组 + */ + install (vm, source) { + vm.commit('d2admin/menu/headerAuth', source) + const { header, aside } = getMenuData(source) + vm.commit('d2admin/menu/headerSet', header) + vm.commit('d2admin/menu/asideSet', aside) + } +} diff --git a/src/menu/modules/demo-components.js b/src/menu/modules/demo-components.js deleted file mode 100644 index 2ff907dd..00000000 --- a/src/menu/modules/demo-components.js +++ /dev/null @@ -1,88 +0,0 @@ -export default { - path: '/demo/components', - title: '组件', - icon: 'puzzle-piece', - children: [ - { path: '/demo/components/index', title: '扩展组件', icon: 'home' }, - { - path: '/demo/components/container', - title: '布局容器', - icon: 'window-restore', - children: [ - { - title: '填充型', - children: [ - { path: '/demo/components/container/full', title: '基础', icon: '' }, - { path: '/demo/components/container/full-slot', title: '插槽', icon: '' }, - { path: '/demo/components/container/full-bs', title: '滚动优化', icon: '' } - ] - }, - { - title: '隐形模式', - children: [ - { path: '/demo/components/container/ghost', title: '基础', icon: '' }, - { path: '/demo/components/container/ghost-slot', title: '插槽', icon: '' }, - { path: '/demo/components/container/ghost-bs', title: '滚动优化', icon: '' } - ] - }, - { - title: '卡片型', - children: [ - { path: '/demo/components/container/card', title: '基础', icon: '' }, - { path: '/demo/components/container/card-slot', title: '插槽', icon: '' }, - { path: '/demo/components/container/card-bs', title: '滚动优化', icon: '' } - ] - }, - { - title: '方法', - children: [ - { path: '/demo/components/container/api?bs=false', title: '滚动控制', icon: '' }, - { path: '/demo/components/container/api?bs=true', title: '滚动控制 BS', icon: '' } - ] - } - ] - }, - { - path: '/demo/components/layout/grid', - title: '高级布局', - icon: 'tasks', - children: [ - { path: '/demo/components/layout/grid', title: '拖拽位置和大小' }, - { path: '/demo/components/layout/splitpane', title: '区域划分' } - ] - }, - { - path: '/demo/components/editor', - title: '编辑器', - icon: 'pencil-square-o', - children: [ - { path: '/demo/components/editor-ueditor', title: 'UEditor', icon: '' }, - { path: '/demo/components/editor-quill', title: 'Quill', icon: '' } - ] - }, - { - path: '/demo/components/icon', - title: '图标', - icon: 'star', - children: [ - { path: '/demo/components/icon/icon', title: '图标组件' }, - { path: '/demo/components/icon/icon-svg', title: 'svg 图标组件' }, - { path: '/demo/components/icon/select', title: '图标选择器' }, - { path: '/demo/components/icon/select-svg', title: 'svg 图标选择器' }, - { path: '/demo/components/icon/list', title: 'FontAwesome' } - ] - }, - { - path: '/demo/components/markdown', - title: 'markdown 解析', - icon: 'file-text-o', - children: [ - { path: '/demo/components/markdown/source', title: '指定资源' }, - { path: '/demo/components/markdown/url', title: '异步加载文件' } - ] - }, - { path: '/demo/components/countup', title: '数字动画', icon: 'motorcycle' }, - { path: '/demo/components/highlight', title: '代码高亮显示', icon: 'code' }, - { path: '/demo/components/json-tree', title: 'JSON 展示', icon: 'sitemap' } - ] -} diff --git a/src/menu/modules/demo-playground.js b/src/menu/modules/demo-playground.js deleted file mode 100644 index d002744d..00000000 --- a/src/menu/modules/demo-playground.js +++ /dev/null @@ -1,133 +0,0 @@ -export default { - path: '/demo/playground', - title: '功能', - icon: 'flask', - children: [ - { path: '/demo/playground/index', title: '功能', icon: 'home' }, - { - title: 'svg 菜单图标', - iconSvg: 'd2-admin', - children: [ - { title: 'add', iconSvg: 'add' }, - { title: 'alarm', iconSvg: 'alarm' }, - { title: 'camera', iconSvg: 'camera' }, - { title: 'history', iconSvg: 'history' }, - { title: 'like', iconSvg: 'like' }, - { title: 'love', iconSvg: 'love' }, - { title: 'message', iconSvg: 'message' }, - { title: 'notice', iconSvg: 'notice' }, - { title: 'search', iconSvg: 'search' }, - { title: 'share', iconSvg: 'share' }, - { title: 'star', iconSvg: 'star' }, - { title: 'user', iconSvg: 'user' } - ] - }, - { - title: '空菜单演示', - icon: 'folder-o', - children: [ - { - title: '正在开发 1', - children: [ - { title: '正在开发 1-1' }, - { title: '正在开发 1-2' } - ] - }, - { title: '正在开发 2' }, - { title: '正在开发 3' } - ] - }, - { - path: '/demo/playground/frame', - title: '内嵌网页', - icon: 'globe', - children: [ - { path: '/demo/playground/frame/d2-doc', title: 'D2Admin 中文文档', iconSvg: 'd2-admin' }, - { path: '/demo/playground/frame/html', title: '静态 HTML', icon: 'code' }, - { path: '/demo/playground/frame/report', title: '构建分析', icon: 'pie-chart' } - ] - }, - { - title: '新窗口打开链接', - icon: 'link', - children: [ - { path: 'https://github.com/d2-projects/d2-admin', title: 'D2Admin Github', icon: 'github' }, - { path: 'https://juejin.im/user/57a48b632e958a006691b946/posts', title: '掘金', icon: 'globe' }, - { path: 'https://my.oschina.net/u/3871516', title: '开源中国', icon: 'globe' }, - { path: 'https://www.zhihu.com/people/fairy-ever/activities', title: '知乎', icon: 'globe' }, - { path: 'https://segmentfault.com/blog/liyang-note-book', title: 'segmentfault 专栏', icon: 'globe' }, - { path: 'http://www.fairyever.com/', title: 'www.fairyever.com', icon: 'globe' } - ] - }, - { - path: '/demo/playground/store', - title: '全局状态管理', - icon: 'bolt', - children: [ - { path: '/demo/playground/store/page', title: '多标签页控制', icon: 'window-restore' }, - { path: '/demo/playground/store/menu', title: '菜单控制', icon: 'bars' }, - { path: '/demo/playground/store/size', title: '全局尺寸', icon: 'font' }, - { path: '/demo/playground/store/ua', title: '浏览器信息', icon: 'info-circle' }, - { path: '/demo/playground/store/gray', title: '灰度模式', icon: 'eye' }, - { path: '/demo/playground/store/fullscreen', title: '全屏', icon: 'arrows-alt' }, - { path: '/demo/playground/store/theme', title: '主题', icon: 'diamond' }, - { path: '/demo/playground/store/transition', title: '页面过渡开关', icon: 'toggle-on' } - ] - }, - { - path: '/demo/playground/page-cache', - title: '页面缓存', - icon: 'hdd-o', - children: [ - { path: '/demo/playground/page-cache/on', title: '开启缓存' }, - { path: '/demo/playground/page-cache/off', title: '关闭缓存' }, - { path: '/demo/playground/page-cache/params/1', title: '带参路由缓存 1' }, - { path: '/demo/playground/page-cache/params/2', title: '带参路由缓存 2' } - ] - }, - { - path: '/demo/playground/page-argu', - title: '参数传递和留存', - icon: 'assistive-listening-systems', - children: [ - { path: '/demo/playground/page-argu/send', title: '发送' }, - { path: '/demo/playground/page-argu/get/username-from-menu?userid=userid-from-menu', title: '接收' } - ] - }, - { - path: '/demo/playground/db', - title: '数据持久化', - icon: 'database', - children: [ - { path: '/demo/playground/db/all', title: '总览', icon: 'table' }, - { path: '/demo/playground/db/public', title: '公共存储', icon: 'users' }, - { path: '/demo/playground/db/user', title: '私有数据', icon: 'user' }, - { path: '/demo/playground/db/page-public', title: '路由存储', icon: 'file-o' }, - { path: '/demo/playground/db/page-user', title: '私有路由存储', icon: 'file-o' }, - { path: '/demo/playground/db/page-snapshot-public', title: '路由快照', icon: 'file' }, - { path: '/demo/playground/db/page-snapshot-user', title: '私有路由快照', icon: 'file' } - ] - }, - { - path: '/demo/playground/log', - title: '日志', - icon: 'bullseye', - children: [ - { path: '/demo/playground/log/log', title: '日志记录', icon: 'dot-circle-o' }, - { path: '/demo/playground/log/error', title: '错误捕捉', icon: 'bug' }, - { path: '/demo/playground/log/ajax', title: 'Ajax 错误', icon: 'bug' }, - { path: '/demo/playground/log/console', title: '控制台日志', icon: 'lightbulb-o' } - ] - }, - { - path: '/demo/playground/add-routes', - title: '动态添加路由', - icon: 'plus-square', - children: [ - { path: '/demo/playground/add-routes/routes', title: '添加页面', icon: 'file-o' } - ] - }, - { path: '/demo/playground/env', title: '环境信息', icon: 'exclamation-circle' }, - { path: '/demo/playground/locales', title: '国际化', icon: 'language' } - ] -} diff --git a/src/menu/modules/demo-plugins.js b/src/menu/modules/demo-plugins.js deleted file mode 100644 index 1cb550db..00000000 --- a/src/menu/modules/demo-plugins.js +++ /dev/null @@ -1,29 +0,0 @@ -export default { - path: '/demo/plugins', - title: '插件', - icon: 'plug', - children: [ - { path: '/demo/plugins/index', title: '插件', icon: 'home' }, - { - path: '/demo/plugins/import', - title: '导入', - icon: 'download', - children: [ - { path: '/demo/plugins/import/csv', title: 'csv' }, - { path: '/demo/plugins/import/xlsx', title: 'xlsx' } - ] - }, - { - path: '/demo/plugins/export', - title: '导出', - icon: 'upload', - children: [ - { path: '/demo/plugins/export/table', title: '表格' }, - { path: '/demo/plugins/export/txt', title: '文本' } - ] - }, - { path: '/demo/plugins/clipboard-polyfill', title: '剪贴板访问', icon: 'clipboard' }, - { path: '/demo/plugins/day', title: '日期计算', icon: 'clock-o' }, - { path: '/demo/plugins/js-cookie', title: 'Cookie 读写', icon: 'asterisk' } - ] -} diff --git a/src/plugin/d2admin/index.js b/src/plugin/d2admin/index.js index 7c739e91..7f56e3c2 100644 --- a/src/plugin/d2admin/index.js +++ b/src/plugin/d2admin/index.js @@ -10,6 +10,8 @@ import '@/assets/svg-icons' // 国际化 import i18n from '@/i18n.js' +import store from '@/store' + // 功能插件 import pluginError from '@/plugin/error' import pluginLog from '@/plugin/log' @@ -28,6 +30,25 @@ export default { Vue.prototype.$version = process.env.VUE_APP_VERSION // 构建时间 Vue.prototype.$buildTime = process.env.VUE_APP_BUILD_TIME + + // 权限检查方法 + Vue.prototype.$permission = (value, type = 'menu') => { + let path = '' + const auth = store.state.d2admin.menu.authKey + + switch (type) { + case 'menu': + path = value + break + case 'router': + path = value.name.replace(/-/g, '/') + path.slice(0, 1) !== '/' && (path = '/' + path) + break + } + + return !!(path && Object.prototype.hasOwnProperty.call(auth, path)) + } + // Element Vue.use(ElementUI, { i18n: (key, value) => i18n.t(key, value) diff --git a/src/router/modules/components.js b/src/router/modules/components.js deleted file mode 100644 index c1a0f402..00000000 --- a/src/router/modules/components.js +++ /dev/null @@ -1,41 +0,0 @@ -import layoutHeaderAside from '@/layout/header-aside' - -// 由于懒加载页面太多的话会造成webpack热更新太慢,所以开发环境不使用懒加载,只有生产环境使用懒加载 -const _import = require('@/libs/util.import.' + process.env.NODE_ENV) - -const meta = { auth: true } - -export default { - path: '/demo/components', - name: 'demo-components', - meta, - redirect: { name: 'demo-components-index' }, - component: layoutHeaderAside, - children: [ - { path: 'container/full', name: 'demo-components-container-full', component: _import('demo/components/container/full.vue'), meta: { ...meta, title: '布局组件 填充' } }, - { path: 'container/full-slot', name: 'demo-components-container-full-slot', component: _import('demo/components/container/full-slot.vue'), meta: { ...meta, title: '布局组件 填充 插槽' } }, - { path: 'container/full-bs', name: 'demo-components-container-full-bs', component: _import('demo/components/container/full-bs.vue'), meta: { ...meta, title: '布局组件 填充 滚动优化' } }, - { path: 'container/ghost', name: 'demo-components-container-ghost', component: _import('demo/components/container/ghost.vue'), meta: { ...meta, title: '布局组件 隐形' } }, - { path: 'container/ghost-slot', name: 'demo-components-container-ghost-slot', component: _import('demo/components/container/ghost-slot.vue'), meta: { ...meta, title: '布局组件 隐形 插槽' } }, - { path: 'container/ghost-bs', name: 'demo-components-container-ghost-bs', component: _import('demo/components/container/ghost-bs.vue'), meta: { ...meta, title: '布局组件 隐形 滚动优化' } }, - { path: 'container/card', name: 'demo-components-container-card', component: _import('demo/components/container/card.vue'), meta: { ...meta, title: '布局组件 卡片' } }, - { path: 'container/card-slot', name: 'demo-components-container-card-slot', component: _import('demo/components/container/card-slot.vue'), meta: { ...meta, title: '布局组件 卡片 插槽' } }, - { path: 'container/card-bs', name: 'demo-components-container-card-bs', component: _import('demo/components/container/card-bs.vue'), meta: { ...meta, title: '布局组件 卡片 滚动优化' } }, - { path: 'container/api', name: 'demo-components-container-api', component: _import('demo/components/container/api.vue'), meta: { ...meta, title: '布局组件 API' } }, - { path: 'countup', name: 'demo-components-countup', component: _import('demo/components/countup'), meta: { ...meta, title: '数字动画' } }, - { path: 'editor-ueditor', name: 'demo-components-editor-ueditor', component: _import('demo/components/editor-ueditor'), meta: { ...meta, title: 'UEditor' } }, - { path: 'editor-quill', name: 'demo-components-editor-quill', component: _import('demo/components/editor-quill'), meta: { ...meta, title: '富文本编辑器' } }, - { path: 'highlight', name: 'demo-components-highlight', component: _import('demo/components/highlight'), meta: { ...meta, title: '代码高亮组件' } }, - { path: 'icon/icon', name: 'demo-components-icon-icon', component: _import('demo/components/icon/icon.vue'), meta: { ...meta, title: '图标组件' } }, - { path: 'icon/icon-svg', name: 'demo-components-icon-icon-svg', component: _import('demo/components/icon/icon-svg.vue'), meta: { ...meta, title: 'svg 图标' } }, - { path: 'icon/select', name: 'demo-components-icon-select', component: _import('demo/components/icon/select.vue'), meta: { ...meta, title: '图标选择器' } }, - { path: 'icon/select-svg', name: 'demo-components-icon-select-svg', component: _import('demo/components/icon/select-svg.vue'), meta: { ...meta, title: 'svg 图标选择器' } }, - { path: 'icon/list', name: 'demo-components-icon-list', component: _import('demo/components/icon/list.vue'), meta: { ...meta, title: '图标列表' } }, - { path: 'index', name: 'demo-components-index', component: _import('demo/components/index'), meta: { ...meta, title: '组件首页' } }, - { path: 'json-tree', name: 'demo-components-json-tree', component: _import('demo/components/json-tree'), meta: { ...meta, title: 'JSON 展示' } }, - { path: 'layout/grid', name: 'demo-components-layout-grid', component: _import('demo/components/layout/grid.vue'), meta: { ...meta, title: '拖拽网格布局' } }, - { path: 'layout/splitpane', name: 'demo-components-layout-splitpane', component: _import('demo/components/layout/splitpane.vue'), meta: { ...meta, title: '区域布局' } }, - { path: 'markdown/source', name: 'demo-components-markdown-source', component: _import('demo/components/markdown/source.vue'), meta: { ...meta, title: 'markdown指定资源渲染' } }, - { path: 'markdown/url', name: 'demo-components-markdown-url', component: _import('demo/components/markdown/url.vue'), meta: { ...meta, title: 'markdown指定url渲染' } } - ] -} diff --git a/src/router/modules/playground.js b/src/router/modules/playground.js deleted file mode 100644 index 3dcc763e..00000000 --- a/src/router/modules/playground.js +++ /dev/null @@ -1,47 +0,0 @@ -import layoutHeaderAside from '@/layout/header-aside' - -// 由于懒加载页面太多的话会造成webpack热更新太慢,所以开发环境不使用懒加载,只有生产环境使用懒加载 -const _import = require('@/libs/util.import.' + process.env.NODE_ENV) - -const meta = { auth: true } - -export default { - path: '/demo/playground', - name: 'demo-playground', - meta, - redirect: { name: 'demo-playground-index' }, - component: layoutHeaderAside, - children: [ - { path: 'index', name: 'demo-playground-index', component: _import('demo/playground/index'), meta: { ...meta, title: '功能首页' } }, - { path: 'store/page', name: 'demo-playground-store-page', component: _import('demo/playground/store/page'), meta: { ...meta, cache: true, title: '多标签页控制' } }, - { path: 'store/menu', name: 'demo-playground-store-menu', component: _import('demo/playground/store/menu'), meta: { ...meta, title: '菜单控制' } }, - { path: 'store/size', name: 'demo-playground-store-size', component: _import('demo/playground/store/size'), meta: { ...meta, title: '全局尺寸' } }, - { path: 'store/ua', name: 'demo-playground-store-ua', component: _import('demo/playground/store/ua'), meta: { ...meta, title: '浏览器信息' } }, - { path: 'store/gray', name: 'demo-playground-store-gray', component: _import('demo/playground/store/gray'), meta: { ...meta, title: '灰度模式' } }, - { path: 'store/fullscreen', name: 'demo-playground-store-fullscreen', component: _import('demo/playground/store/fullscreen'), meta: { ...meta, title: '全屏' } }, - { path: 'store/theme', name: 'demo-playground-store-theme', component: _import('demo/playground/store/theme'), meta: { ...meta, title: '主题' } }, - { path: 'store/transition', name: 'demo-playground-store-transition', component: _import('demo/playground/store/transition'), meta: { ...meta, title: '页面过渡开关' } }, - { path: 'page-cache/on', name: 'demo-playground-page-cache-on', component: _import('demo/playground/page-cache/on.vue'), meta: { ...meta, cache: true, title: '开启缓存' } }, - { path: 'page-cache/off', name: 'demo-playground-page-cache-off', component: _import('demo/playground/page-cache/off.vue'), meta: { ...meta, title: '关闭缓存' } }, - { path: 'page-cache/params/:id', name: 'demo-playground-page-cache-params', component: _import('demo/playground/page-cache/params.vue'), meta: { ...meta, cache: true, title: '带参路由缓存' }, props: true }, - { path: 'page-argu/send', name: 'demo-playground-page-argu-send', component: _import('demo/playground/page-argu/send.vue'), meta: { ...meta, title: '参数传递 发送' } }, - { path: 'page-argu/get/:username', name: 'demo-playground-page-argu-get', component: _import('demo/playground/page-argu/get.vue'), meta: { ...meta, title: '参数传递 接收' } }, - { path: 'db/all', name: 'demo-playground-db-all', component: _import('demo/playground/db/all'), meta: { ...meta, title: '总览' } }, - { path: 'db/public', name: 'demo-playground-db-public', component: _import('demo/playground/db/public'), meta: { ...meta, title: '公共存储' } }, - { path: 'db/user', name: 'demo-playground-db-user', component: _import('demo/playground/db/user'), meta: { ...meta, title: '私有存储' } }, - { path: 'db/page-public', name: 'demo-playground-db-page-public', component: _import('demo/playground/db/page-public'), meta: { ...meta, title: '路由存储' } }, - { path: 'db/page-user', name: 'demo-playground-db-page-user', component: _import('demo/playground/db/page-user'), meta: { ...meta, title: '私有路由存储' } }, - { path: 'db/page-snapshot-public', name: 'demo-playground-db-page-snapshot-public', component: _import('demo/playground/db/page-snapshot-public'), meta: { ...meta, title: '路由快照' } }, - { path: 'db/page-snapshot-user', name: 'demo-playground-db-page-snapshot-user', component: _import('demo/playground/db/page-snapshot-user'), meta: { ...meta, title: '私有路由快照' } }, - { path: 'log/ajax', name: 'demo-playground-log-ajax', component: _import('demo/playground/log/ajax'), meta: { ...meta, title: 'Ajax 错误' } }, - { path: 'log/console', name: 'demo-playground-log-console', component: _import('demo/playground/log/console'), meta: { ...meta, title: '控制台日志' } }, - { path: 'log/error', name: 'demo-playground-log-error', component: _import('demo/playground/log/error'), meta: { ...meta, title: '错误捕捉' } }, - { path: 'log/log', name: 'demo-playground-log-log', component: _import('demo/playground/log/log'), meta: { ...meta, title: '日志记录' } }, - { path: 'add-routes/routes', name: 'demo-playground-add-routes-routes', component: _import('demo/playground/add-routes/routes'), meta: { ...meta, title: '添加页面' } }, - { path: 'env', name: 'demo-playground-env', component: _import('demo/playground/env'), meta: { ...meta, title: '环境信息' } }, - { path: 'locales', name: 'demo-playground-locales', component: _import('demo/playground/locales'), meta: { ...meta, title: '国际化' } }, - { path: 'frame/html', name: 'demo-playground-frame-html', component: _import('demo/playground/frame/html'), meta: { ...meta, title: '静态 HTML' } }, - { path: 'frame/report', name: 'demo-playground-frame-report', component: _import('demo/playground/frame/report'), meta: { ...meta, title: 'Size report' } }, - { path: 'frame/d2-doc', name: 'demo-playground-frame-d2-doc', component: _import('demo/playground/frame/d2-doc'), meta: { ...meta, title: 'D2Admin 中文文档' } } - ] -} diff --git a/src/router/modules/plugins.js b/src/router/modules/plugins.js deleted file mode 100644 index 302506e4..00000000 --- a/src/router/modules/plugins.js +++ /dev/null @@ -1,24 +0,0 @@ -import layoutHeaderAside from '@/layout/header-aside' - -// 由于懒加载页面太多的话会造成webpack热更新太慢,所以开发环境不使用懒加载,只有生产环境使用懒加载 -const _import = require('@/libs/util.import.' + process.env.NODE_ENV) - -const meta = { auth: true } - -export default { - path: '/demo/plugins', - name: 'demo-plugins', - meta, - redirect: { name: 'demo-plugins-index' }, - component: layoutHeaderAside, - children: [ - { path: 'clipboard-polyfill', name: 'demo-plugins-clipboard-polyfill', component: _import('demo/plugins/clipboard-polyfill'), meta: { ...meta, title: '剪贴板访问' } }, - { path: 'day', name: 'demo-plugins-day', component: _import('demo/plugins/day'), meta: { ...meta, title: '日期计算' } }, - { path: 'export/table', name: 'demo-plugins-export-table', component: _import('demo/plugins/export/table.vue'), meta: { ...meta, title: '导出表格' } }, - { path: 'export/txt', name: 'demo-plugins-export-txt', component: _import('demo/plugins/export/txt.vue'), meta: { ...meta, title: '导出文本' } }, - { path: 'import/csv', name: 'demo-plugins-import-csv', component: _import('demo/plugins/import/csv.vue'), meta: { ...meta, title: '导入 csv' } }, - { path: 'import/xlsx', name: 'demo-plugins-import-xlsx', component: _import('demo/plugins/import/xlsx.vue'), meta: { ...meta, title: '导入 xlsx' } }, - { path: 'index', name: 'demo-plugins-index', component: _import('demo/plugins/index'), meta: { ...meta, title: '插件首页' } }, - { path: 'js-cookie', name: 'demo-plugins-js-cookie', component: _import('demo/plugins/js-cookie'), meta: { ...meta, title: 'Cookie' } } - ] -} diff --git a/src/router/modules/production-master-data.js b/src/router/modules/production-master-data.js deleted file mode 100644 index e91fc9a1..00000000 --- a/src/router/modules/production-master-data.js +++ /dev/null @@ -1,18 +0,0 @@ -import layoutHeaderAside from '@/layout/header-aside' - -const meta = { auth: true } - -const _import = require('@/libs/util.import.' + process.env.NODE_ENV) - -export default { - path: '/production_master_data', - component: layoutHeaderAside, - children: (pre => [ - { - path: 'factory_model/factory_area', - name: `${pre}factory_model-factory_area`, - meta: { ...meta, cache: true, title: '工厂区域' }, - component: _import('production-master-data/factory-model/factory-area') - } - ])('production_master_data-') -} diff --git a/src/router/routes.js b/src/router/routes.js index 52a7b00f..7652ebd2 100644 --- a/src/router/routes.js +++ b/src/router/routes.js @@ -1,9 +1,5 @@ -import playground from './modules/playground' -import plugins from './modules/plugins' -import components from './modules/components' -import productionMasterData from './modules/production-master-data' - import layoutHeaderAside from '@/layout/header-aside' +import productionMasterData from './modules/production-master-data' // 由于懒加载页面太多的话会造成webpack热更新太慢,所以开发环境不使用懒加载,只有生产环境使用懒加载 const _import = require('@/libs/util.import.' + process.env.NODE_ENV) @@ -53,9 +49,6 @@ const frameIn = [ } ] }, - playground, - plugins, - components, productionMasterData ] diff --git a/src/store/modules/d2admin/modules/menu.js b/src/store/modules/d2admin/modules/menu.js index 520e2d60..8a791ec4 100644 --- a/src/store/modules/d2admin/modules/menu.js +++ b/src/store/modules/d2admin/modules/menu.js @@ -1,5 +1,7 @@ -// 设置文件 import setting from '@/setting.js' +import util from '@/libs/util' +import menu from '@/menu' +import { getMenuAll } from '@/api/menu' export default { namespaced: true, @@ -12,19 +14,14 @@ export default { asideCollapse: setting.menu.asideCollapse, // 侧边栏折叠动画 asideTransition: setting.menu.asideTransition, + // 权限字典 { '/path': '菜单名' } + authKey: {}, // 菜单源数据 sourceData: [] }, actions: { - /** - * 设置侧边栏展开或者收缩 - * @param {Object} context - * @param {Boolean} collapse is collapse - */ async asideCollapseSet ({ state, dispatch }, collapse) { - // store 赋值 state.asideCollapse = collapse - // 持久化 await dispatch('d2admin/db/set', { dbName: 'sys', path: 'menu.asideCollapse', @@ -32,14 +29,8 @@ export default { user: true }, { root: true }) }, - /** - * 切换侧边栏展开和收缩 - * @param {Object} context - */ async asideCollapseToggle ({ state, dispatch }) { - // store 赋值 state.asideCollapse = !state.asideCollapse - // 持久化 await dispatch('d2admin/db/set', { dbName: 'sys', path: 'menu.asideCollapse', @@ -47,15 +38,8 @@ export default { user: true }, { root: true }) }, - /** - * 设置侧边栏折叠动画 - * @param {Object} context - * @param {Boolean} transition is transition - */ async asideTransitionSet ({ state, dispatch }, transition) { - // store 赋值 state.asideTransition = transition - // 持久化 await dispatch('d2admin/db/set', { dbName: 'sys', path: 'menu.asideTransition', @@ -63,14 +47,8 @@ export default { user: true }, { root: true }) }, - /** - * 切换侧边栏折叠动画 - * @param {Object} context - */ async asideTransitionToggle ({ state, dispatch }) { - // store 赋值 state.asideTransition = !state.asideTransition - // 持久化 await dispatch('d2admin/db/set', { dbName: 'sys', path: 'menu.asideTransition', @@ -78,52 +56,58 @@ export default { user: true }, { root: true }) }, - /** - * 持久化数据加载侧边栏设置 - * @param {Object} context - */ async asideLoad ({ state, dispatch }) { - // store 赋值 - const menu = await dispatch('d2admin/db/get', { + const menuSetting = await dispatch('d2admin/db/get', { dbName: 'sys', path: 'menu', defaultValue: setting.menu, user: true }, { root: true }) - state.asideCollapse = menu.asideCollapse !== undefined ? menu.asideCollapse : setting.menu.asideCollapse - state.asideTransition = menu.asideTransition !== undefined ? menu.asideTransition : setting.menu.asideTransition + state.asideCollapse = menuSetting.asideCollapse !== undefined ? menuSetting.asideCollapse : setting.menu.asideCollapse + state.asideTransition = menuSetting.asideTransition !== undefined ? menuSetting.asideTransition : setting.menu.asideTransition }, - /** - * 持久化数据加载菜单源数据 - * @param {Object} context - */ - async sourceDataLoad ({ state, dispatch }) { - const sourceData = await dispatch('d2admin/db/get', { + async sourceDataLoad ({ state, commit, dispatch }) { + // 优先从 localStorage 读取上次缓存的菜单数据 + state.sourceData = await dispatch('d2admin/db/get', { dbName: 'database', path: '$menu.sourceData', defaultValue: [], user: true }, { root: true }) - state.sourceData = sourceData + + // 缓存为空且已登录时,从后端获取菜单 + if (!state.sourceData.length && util.cookies.get('token')) { + const res = await getMenuAll() + state.sourceData = res || [] + await dispatch('d2admin/db/set', { + dbName: 'database', + path: '$menu.sourceData', + value: state.sourceData, + user: true + }, { root: true }) + } + + // 构建菜单树和权限字典 + menu.install(this, state.sourceData) } }, mutations: { - /** - * @description 设置顶栏菜单 - * @param {Object} state state - * @param {Array} menu menu setting - */ + headerAuth (state, source) { + if (!source || source.length <= 0) { + return + } + const auth = {} + source.forEach(value => { + if (value.url) { + auth[value.url] = value.name + } + }) + state.authKey = auth + }, headerSet (state, menu) { - // store 赋值 state.header = menu }, - /** - * @description 设置侧边栏菜单 - * @param {Object} state state - * @param {Array} menu menu setting - */ asideSet (state, menu) { - // store 赋值 state.aside = menu } } diff --git a/src/views/demo/components/container/api.vue b/src/views/demo/components/container/api.vue deleted file mode 100644 index e021348d..00000000 --- a/src/views/demo/components/container/api.vue +++ /dev/null @@ -1,104 +0,0 @@ - - - diff --git a/src/views/demo/components/container/card-bs.vue b/src/views/demo/components/container/card-bs.vue deleted file mode 100644 index e1312736..00000000 --- a/src/views/demo/components/container/card-bs.vue +++ /dev/null @@ -1,16 +0,0 @@ - - - diff --git a/src/views/demo/components/container/card-slot.vue b/src/views/demo/components/container/card-slot.vue deleted file mode 100644 index ff8b63df..00000000 --- a/src/views/demo/components/container/card-slot.vue +++ /dev/null @@ -1,16 +0,0 @@ - - - diff --git a/src/views/demo/components/container/card.vue b/src/views/demo/components/container/card.vue deleted file mode 100644 index ec121617..00000000 --- a/src/views/demo/components/container/card.vue +++ /dev/null @@ -1,14 +0,0 @@ - - - diff --git a/src/views/demo/components/container/components/d2-demo-article.vue b/src/views/demo/components/container/components/d2-demo-article.vue deleted file mode 100644 index 00dc1b43..00000000 --- a/src/views/demo/components/container/components/d2-demo-article.vue +++ /dev/null @@ -1,50 +0,0 @@ - - - - - diff --git a/src/views/demo/components/container/full-bs.vue b/src/views/demo/components/container/full-bs.vue deleted file mode 100644 index 9a651025..00000000 --- a/src/views/demo/components/container/full-bs.vue +++ /dev/null @@ -1,16 +0,0 @@ - - - diff --git a/src/views/demo/components/container/full-slot.vue b/src/views/demo/components/container/full-slot.vue deleted file mode 100644 index 087df2a9..00000000 --- a/src/views/demo/components/container/full-slot.vue +++ /dev/null @@ -1,16 +0,0 @@ - - - diff --git a/src/views/demo/components/container/full.vue b/src/views/demo/components/container/full.vue deleted file mode 100644 index 9d99c936..00000000 --- a/src/views/demo/components/container/full.vue +++ /dev/null @@ -1,14 +0,0 @@ - - - diff --git a/src/views/demo/components/container/ghost-bs.vue b/src/views/demo/components/container/ghost-bs.vue deleted file mode 100644 index bb41da3b..00000000 --- a/src/views/demo/components/container/ghost-bs.vue +++ /dev/null @@ -1,20 +0,0 @@ - - - diff --git a/src/views/demo/components/container/ghost-slot.vue b/src/views/demo/components/container/ghost-slot.vue deleted file mode 100644 index 831594da..00000000 --- a/src/views/demo/components/container/ghost-slot.vue +++ /dev/null @@ -1,20 +0,0 @@ - - - diff --git a/src/views/demo/components/container/ghost.vue b/src/views/demo/components/container/ghost.vue deleted file mode 100644 index 2c9872c3..00000000 --- a/src/views/demo/components/container/ghost.vue +++ /dev/null @@ -1,18 +0,0 @@ - - - diff --git a/src/views/demo/components/container/md/long.md b/src/views/demo/components/container/md/long.md deleted file mode 100644 index 59d2f891..00000000 --- a/src/views/demo/components/container/md/long.md +++ /dev/null @@ -1,53 +0,0 @@ -## vue.js - -**易用** - -已经会了 HTML、CSS、JavaScript?即刻阅读指南开始构建应用! - -**灵活** - -不断繁荣的生态系统,可以在一个库和一套完整框架之间自如伸缩。 - -**高效** - -20kB min+gzip 运行大小 - -超快虚拟 DOM - -最省心的优化 - -**Vue.js 是什么** - -Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。另一方面,当与现代化的工具链以及各种支持类库结合使用时,Vue 也完全能够为复杂的单页应用提供驱动。 - -如果你已经是有经验的前端开发者,想知道 Vue 与其它库/框架有哪些区别,请查看对比其它框架。 - -## Element - -Element,一套为开发者、设计师和产品经理准备的基于 Vue 2.0 的桌面端组件库 - -**一致性** Consistency - -- 与现实生活一致:与现实生活的流程、逻辑保持一致,遵循用户习惯的语言和概念; - -- 在界面中一致:所有的元素和结构需保持一致,比如:设计样式、图标和文本、元素的位置等。 - -**反馈** Feedback - -- 控制反馈:通过界面样式和交互动效让用户可以清晰的感知自己的操作; - -- 页面反馈:操作后,通过页面元素的变化清晰地展现当前状态。 - -**效率** Efficiency - -- 简化流程:设计简洁直观的操作流程; - -- 清晰明确:语言表达清晰且表意明确,让用户快速理解进而作出决策; - -- 帮助用户识别:界面简单直白,让用户快速识别而非回忆,减少用户记忆负担。 - -**可控** Controllability - -- 用户决策:根据场景可给予用户操作建议或安全提示,但不能代替用户进行决策; - -- 结果可控:用户可以自由的进行操作,包括撤销、回退和终止当前操作等。 \ No newline at end of file diff --git a/src/views/demo/components/container/md/short.md b/src/views/demo/components/container/md/short.md deleted file mode 100644 index 06496563..00000000 --- a/src/views/demo/components/container/md/short.md +++ /dev/null @@ -1,17 +0,0 @@ -## vue.js - -**易用** - -已经会了 HTML、CSS、JavaScript?即刻阅读指南开始构建应用! - -**灵活** - -不断繁荣的生态系统,可以在一个库和一套完整框架之间自如伸缩。 - -**高效** - -20kB min+gzip 运行大小 - -超快虚拟 DOM - -最省心的优化 \ No newline at end of file diff --git a/src/views/demo/components/countup/index.vue b/src/views/demo/components/countup/index.vue deleted file mode 100644 index 9e952b8d..00000000 --- a/src/views/demo/components/countup/index.vue +++ /dev/null @@ -1,94 +0,0 @@ - - - - - diff --git a/src/views/demo/components/editor-quill/index.vue b/src/views/demo/components/editor-quill/index.vue deleted file mode 100644 index dc456e55..00000000 --- a/src/views/demo/components/editor-quill/index.vue +++ /dev/null @@ -1,49 +0,0 @@ - - - diff --git a/src/views/demo/components/editor-quill/value.js b/src/views/demo/components/editor-quill/value.js deleted file mode 100644 index 89744593..00000000 --- a/src/views/demo/components/editor-quill/value.js +++ /dev/null @@ -1,6 +0,0 @@ -export default `

-D2 Admin - -by -vue.js -

` diff --git a/src/views/demo/components/editor-ueditor/index.vue b/src/views/demo/components/editor-ueditor/index.vue deleted file mode 100644 index c2d0ab3f..00000000 --- a/src/views/demo/components/editor-ueditor/index.vue +++ /dev/null @@ -1,33 +0,0 @@ - - - diff --git a/src/views/demo/components/highlight/code/css.js b/src/views/demo/components/highlight/code/css.js deleted file mode 100644 index f41e0a90..00000000 --- a/src/views/demo/components/highlight/code/css.js +++ /dev/null @@ -1,8 +0,0 @@ -export default `body { - background-color: aliceblue; - height: 100%; -} -.my-card { - height: 300px; - width: 300px; -}` diff --git a/src/views/demo/components/highlight/code/html.js b/src/views/demo/components/highlight/code/html.js deleted file mode 100644 index 739a2b9d..00000000 --- a/src/views/demo/components/highlight/code/html.js +++ /dev/null @@ -1,8 +0,0 @@ -export default `` diff --git a/src/views/demo/components/highlight/code/javascript.js b/src/views/demo/components/highlight/code/javascript.js deleted file mode 100644 index ce752335..00000000 --- a/src/views/demo/components/highlight/code/javascript.js +++ /dev/null @@ -1,3 +0,0 @@ -export default `[].forEach.call($$("*"), a => { - a.style.outline="1px solid #"+(~~(Math.random()*(1<<24))).toString(16) -})` diff --git a/src/views/demo/components/highlight/code/scss.js b/src/views/demo/components/highlight/code/scss.js deleted file mode 100644 index d914909c..00000000 --- a/src/views/demo/components/highlight/code/scss.js +++ /dev/null @@ -1,8 +0,0 @@ -export default `body { - background-color: aliceblue; - height: 100%; - .my-card { - height: 300px; - width: 300px; - } -}` diff --git a/src/views/demo/components/highlight/index.vue b/src/views/demo/components/highlight/index.vue deleted file mode 100644 index ea77e68a..00000000 --- a/src/views/demo/components/highlight/index.vue +++ /dev/null @@ -1,38 +0,0 @@ - - - diff --git a/src/views/demo/components/icon/components/d2-icon-cell.vue b/src/views/demo/components/icon/components/d2-icon-cell.vue deleted file mode 100644 index 603004f0..00000000 --- a/src/views/demo/components/icon/components/d2-icon-cell.vue +++ /dev/null @@ -1,82 +0,0 @@ - - - - - diff --git a/src/views/demo/components/icon/data/index.js b/src/views/demo/components/icon/data/index.js deleted file mode 100644 index 3283c245..00000000 --- a/src/views/demo/components/icon/data/index.js +++ /dev/null @@ -1,1004 +0,0 @@ -// 4.7.0 - -export default [ - { - title: '网页', - icon: [ - 'address-book', - 'address-book-o', - 'address-card', - 'address-card-o', - 'adjust', - 'american-sign-language-interpreting', - 'anchor', - 'archive', - 'area-chart', - 'arrows', - 'arrows-h', - 'arrows-v', - 'asl-interpreting', - 'assistive-listening-systems', - 'asterisk', - 'at', - 'audio-description', - 'automobile', - 'balance-scale', - 'ban', - 'bank', - 'bar-chart', - 'bar-chart-o', - 'barcode', - 'bars', - 'bath', - 'bathtub', - 'battery', - 'battery-0', - 'battery-1', - 'battery-2', - 'battery-3', - 'battery-4', - 'battery-empty', - 'battery-full', - 'battery-half', - 'battery-quarter', - 'battery-three-quarters', - 'bed', - 'beer', - 'bell', - 'bell-o', - 'bell-slash', - 'bell-slash-o', - 'bicycle', - 'binoculars', - 'birthday-cake', - 'blind', - 'bluetooth', - 'bluetooth-b', - 'bolt', - 'bomb', - 'book', - 'bookmark', - 'bookmark-o', - 'braille', - 'briefcase', - 'bug', - 'building', - 'building-o', - 'bullhorn', - 'bullseye', - 'bus', - 'cab', - 'calculator', - 'calendar', - 'calendar-check-o', - 'calendar-minus-o', - 'calendar-o', - 'calendar-plus-o', - 'calendar-times-o', - 'camera', - 'camera-retro', - 'car', - 'caret-square-o-down', - 'caret-square-o-left', - 'caret-square-o-right', - 'caret-square-o-up', - 'cart-arrow-down', - 'cart-plus', - 'cc', - 'certificate', - 'check', - 'check-circle', - 'check-circle-o', - 'check-square', - 'check-square-o', - 'child', - 'circle', - 'circle-o', - 'circle-o-notch', - 'circle-thin', - 'clock-o', - 'clone', - 'close', - 'cloud', - 'cloud-download', - 'cloud-upload', - 'code', - 'code-fork', - 'coffee', - 'cog', - 'cogs', - 'comment', - 'comment-o', - 'commenting', - 'commenting-o', - 'comments', - 'comments-o', - 'compass', - 'copyright', - 'creative-commons', - 'credit-card', - 'credit-card-alt', - 'crop', - 'crosshairs', - 'cube', - 'cubes', - 'cutlery', - 'index', - 'database', - 'deaf', - 'deafness', - 'desktop', - 'diamond', - 'dot-circle-o', - 'download', - 'drivers-license', - 'drivers-license-o', - 'edit', - 'ellipsis-h', - 'ellipsis-v', - 'envelope', - 'envelope-o', - 'envelope-open', - 'envelope-open-o', - 'envelope-square', - 'eraser', - 'exchange', - 'exclamation', - 'exclamation-circle', - 'exclamation-triangle', - 'external-link', - 'external-link-square', - 'eye', - 'eye-slash', - 'eyedropper', - 'fax', - 'feed', - 'female', - 'fighter-jet', - 'file-archive-o', - 'file-audio-o', - 'file-code-o', - 'file-excel-o', - 'file-image-o', - 'file-movie-o', - 'file-pdf-o', - 'file-photo-o', - 'file-picture-o', - 'file-powerpoint-o', - 'file-sound-o', - 'file-video-o', - 'file-word-o', - 'file-zip-o', - 'film', - 'filter', - 'fire', - 'fire-extinguisher', - 'flag', - 'flag-checkered', - 'flag-o', - 'flash', - 'flask', - 'folder', - 'folder-o', - 'folder-open', - 'folder-open-o', - 'frown-o', - 'futbol-o', - 'gamepad', - 'gavel', - 'gear', - 'gears', - 'gift', - 'glass', - 'globe', - 'graduation-cap', - 'group', - 'hand-grab-o', - 'hand-lizard-o', - 'hand-paper-o', - 'hand-peace-o', - 'hand-pointer-o', - 'hand-rock-o', - 'hand-scissors-o', - 'hand-spock-o', - 'hand-stop-o', - 'handshake-o', - 'hard-of-hearing', - 'hashtag', - 'hdd-o', - 'headphones', - 'heart', - 'heart-o', - 'heartbeat', - 'history', - 'home', - 'hotel', - 'hourglass', - 'hourglass-1', - 'hourglass-2', - 'hourglass-3', - 'hourglass-end', - 'hourglass-half', - 'hourglass-o', - 'hourglass-start', - 'i-cursor', - 'id-badge', - 'id-card', - 'id-card-o', - 'image', - 'inbox', - 'industry', - 'info', - 'info-circle', - 'institution', - 'key', - 'keyboard-o', - 'language', - 'laptop', - 'leaf', - 'legal', - 'lemon-o', - 'level-down', - 'level-up', - 'life-bouy', - 'life-buoy', - 'life-ring', - 'life-saver', - 'lightbulb-o', - 'line-chart', - 'location-arrow', - 'lock', - 'low-vision', - 'magic', - 'magnet', - 'mail-forward', - 'mail-reply', - 'mail-reply-all', - 'male', - 'map', - 'map-marker', - 'map-o', - 'map-pin', - 'map-signs', - 'meh-o', - 'microchip', - 'microphone', - 'microphone-slash', - 'minus', - 'minus-circle', - 'minus-square', - 'minus-square-o', - 'mobile', - 'mobile-phone', - 'money', - 'moon-o', - 'mortar-board', - 'motorcycle', - 'mouse-pointer', - 'music', - 'navicon', - 'newspaper-o', - 'object-group', - 'object-ungroup', - 'paint-brush', - 'paper-plane', - 'paper-plane-o', - 'paw', - 'pencil', - 'pencil-square', - 'pencil-square-o', - 'percent', - 'phone', - 'phone-square', - 'photo', - 'picture-o', - 'pie-chart', - 'plane', - 'plug', - 'plus', - 'plus-circle', - 'plus-square', - 'plus-square-o', - 'podcast', - 'power-off', - 'print', - 'puzzle-piece', - 'qrcode', - 'question', - 'question-circle', - 'question-circle-o', - 'quote-left', - 'quote-right', - 'random', - 'recycle', - 'refresh', - 'registered', - 'remove', - 'reorder', - 'reply', - 'reply-all', - 'retweet', - 'road', - 'rocket', - 'rss', - 'rss-square', - 's15', - 'search', - 'search-minus', - 'search-plus', - 'send', - 'send-o', - 'server', - 'share', - 'share-alt', - 'share-alt-square', - 'share-square', - 'share-square-o', - 'shield', - 'ship', - 'shopping-bag', - 'shopping-basket', - 'shopping-cart', - 'shower', - 'sign-in', - 'sign-language', - 'sign-out', - 'signal', - 'signing', - 'sitemap', - 'sliders', - 'smile-o', - 'snowflake-o', - 'soccer-ball-o', - 'sort', - 'sort-alpha-asc', - 'sort-alpha-desc', - 'sort-amount-asc', - 'sort-amount-desc', - 'sort-asc', - 'sort-desc', - 'sort-down', - 'sort-numeric-asc', - 'sort-numeric-desc', - 'sort-up', - 'space-shuttle', - 'spinner', - 'spoon', - 'square', - 'square-o', - 'star', - 'star-half', - 'star-half-empty', - 'star-half-full', - 'star-half-o', - 'star-o', - 'sticky-note', - 'sticky-note-o', - 'street-view', - 'suitcase', - 'sun-o', - 'support', - 'tablet', - 'tachometer', - 'tag', - 'tags', - 'tasks', - 'taxi', - 'television', - 'terminal', - 'thermometer', - 'thermometer-0', - 'thermometer-1', - 'thermometer-2', - 'thermometer-3', - 'thermometer-4', - 'thermometer-empty', - 'thermometer-full', - 'thermometer-half', - 'thermometer-quarter', - 'thermometer-three-quarters', - 'thumb-tack', - 'thumbs-down', - 'thumbs-o-down', - 'thumbs-o-up', - 'thumbs-up', - 'ticket', - 'times', - 'times-circle', - 'times-circle-o', - 'times-rectangle', - 'times-rectangle-o', - 'tint', - 'toggle-down', - 'toggle-left', - 'toggle-off', - 'toggle-on', - 'toggle-right', - 'toggle-up', - 'trademark', - 'trash', - 'trash-o', - 'tree', - 'trophy', - 'truck', - 'tty', - 'tv', - 'umbrella', - 'universal-access', - 'university', - 'unlock', - 'unlock-alt', - 'unsorted', - 'upload', - 'user', - 'user-circle', - 'user-circle-o', - 'user-o', - 'user-plus', - 'user-secret', - 'user-times', - 'users', - 'vcard', - 'vcard-o', - 'video-camera', - 'volume-control-phone', - 'volume-down', - 'volume-off', - 'volume-up', - 'warning', - 'wheelchair', - 'wheelchair-alt', - 'wifi', - 'window-close', - 'window-close-o', - 'window-maximize', - 'window-minimize', - 'window-restore', - 'wrench' - ] - }, - { - title: '辅助功能', - icon: [ - 'american-sign-language-interpreting', - 'asl-interpreting', - 'assistive-listening-systems', - 'audio-description', - 'blind', - 'braille', - 'cc', - 'deaf', - 'deafness', - 'hard-of-hearing', - 'low-vision', - 'question-circle-o', - 'sign-language', - 'signing', - 'tty', - 'universal-access', - 'volume-control-phone', - 'wheelchair', - 'wheelchair-alt' - ] - }, - { - title: '手势', - icon: [ - 'hand-grab-o', - 'hand-lizard-o', - 'hand-o-down', - 'hand-o-left', - 'hand-o-right', - 'hand-o-up', - 'hand-paper-o', - 'hand-peace-o', - 'hand-pointer-o', - 'hand-rock-o', - 'hand-scissors-o', - 'hand-spock-o', - 'hand-stop-o', - 'thumbs-down', - 'thumbs-o-down', - 'thumbs-o-up', - 'thumbs-up' - ] - }, - { - title: '运输', - icon: [ - 'ambulance', - 'automobile', - 'bicycle', - 'bus', - 'cab', - 'car', - 'fighter-jet', - 'motorcycle', - 'plane', - 'rocket', - 'ship', - 'space-shuttle', - 'subway', - 'taxi', - 'train', - 'truck', - 'wheelchair', - 'wheelchair-alt' - ] - }, - { - title: '性别', - icon: [ - 'genderless', - 'intersex', - 'mars', - 'mars-double', - 'mars-stroke', - 'mars-stroke-h', - 'mars-stroke-v', - 'mercury', - 'neuter', - 'transgender', - 'transgender-alt', - 'venus', - 'venus-double', - 'venus-mars' - ] - }, - { - title: '文件类型', - icon: [ - 'file', - 'file-archive-o', - 'file-audio-o', - 'file-code-o', - 'file-excel-o', - 'file-image-o', - 'file-movie-o', - 'file-o', - 'file-pdf-o', - 'file-photo-o', - 'file-picture-o', - 'file-powerpoint-o', - 'file-sound-o', - 'file-text', - 'file-text-o', - 'file-video-o', - 'file-word-o', - 'file-zip-o' - ] - }, - { - title: '可旋转', - icon: [ - 'circle-o-notch', - 'cog', - 'gear', - 'refresh', - 'spinner' - ] - }, - { - title: '表单', - icon: [ - 'check-square', - 'check-square-o', - 'circle', - 'circle-o', - 'dot-circle-o', - 'minus-square', - 'minus-square-o', - 'plus-square', - 'plus-square-o', - 'square', - 'square-o' - ] - }, - { - title: '支付', - icon: [ - 'cc-amex', - 'cc-diners-club', - 'cc-discover', - 'cc-jcb', - 'cc-mastercard', - 'cc-paypal', - 'cc-stripe', - 'cc-visa', - 'credit-card', - 'credit-card-alt', - 'google-wallet', - 'paypal' - ] - }, - { - title: '图表', - icon: [ - 'area-chart', - 'bar-chart', - 'bar-chart-o', - 'line-chart', - 'pie-chart' - ] - }, - { - title: '货币', - icon: [ - 'bitcoin', - 'btc', - 'cny', - 'dollar', - 'eur', - 'euro', - 'gbp', - 'gg', - 'gg-circle', - 'ils', - 'inr', - 'jpy', - 'krw', - 'money', - 'rmb', - 'rouble', - 'rub', - 'ruble', - 'rupee', - 'shekel', - 'sheqel', - 'try', - 'turkish-lira', - 'usd', - 'won', - 'yen' - ] - }, - { - title: '文本编辑', - icon: [ - 'align-center', - 'align-justify', - 'align-left', - 'align-right', - 'bold', - 'chain', - 'chain-broken', - 'clipboard', - 'columns', - 'copy', - 'cut', - 'dedent', - 'eraser', - 'file', - 'file-o', - 'file-text', - 'file-text-o', - 'files-o', - 'floppy-o', - 'font', - 'header', - 'indent', - 'italic', - 'link', - 'list', - 'list-alt', - 'list-ol', - 'list-ul', - 'outdent', - 'paperclip', - 'paragraph', - 'paste', - 'repeat', - 'rotate-left', - 'rotate-right', - 'save', - 'scissors', - 'strikethrough', - 'subscript', - 'superscript', - 'table', - 'text-height', - 'text-width', - 'th', - 'th-large', - 'th-list', - 'underline', - 'undo', - 'unlink' - ] - }, - { - title: '指示方向', - icon: [ - 'angle-double-down', - 'angle-double-left', - 'angle-double-right', - 'angle-double-up', - 'angle-down', - 'angle-left', - 'angle-right', - 'angle-up', - 'arrow-circle-down', - 'arrow-circle-left', - 'arrow-circle-o-down', - 'arrow-circle-o-left', - 'arrow-circle-o-right', - 'arrow-circle-o-up', - 'arrow-circle-right', - 'arrow-circle-up', - 'arrow-down', - 'arrow-left', - 'arrow-right', - 'arrow-up', - 'arrows', - 'arrows-alt', - 'arrows-h', - 'arrows-v', - 'caret-down', - 'caret-left', - 'caret-right', - 'caret-square-o-down', - 'caret-square-o-left', - 'caret-square-o-right', - 'caret-square-o-up', - 'caret-up', - 'chevron-circle-down', - 'chevron-circle-left', - 'chevron-circle-right', - 'chevron-circle-up', - 'chevron-down', - 'chevron-left', - 'chevron-right', - 'chevron-up', - 'exchange', - 'hand-o-down', - 'hand-o-left', - 'hand-o-right', - 'hand-o-up', - 'long-arrow-down', - 'long-arrow-left', - 'long-arrow-right', - 'long-arrow-up', - 'toggle-down', - 'toggle-left', - 'toggle-right', - 'toggle-up' - ] - }, - { - title: '视频播放', - icon: [ - 'arrows-alt', - 'backward', - 'compress', - 'eject', - 'expand', - 'fast-backward', - 'fast-forward', - 'forward', - 'pause', - 'pause-circle', - 'pause-circle-o', - 'play', - 'play-circle', - 'play-circle-o', - 'random', - 'step-backward', - 'step-forward', - 'stop', - 'stop-circle', - 'stop-circle-o', - 'youtube-play' - ] - }, - { - title: '标志', - icon: [ - '500px', - 'adn', - 'amazon', - 'android', - 'angellist', - 'apple', - 'bandcamp', - 'behance', - 'behance-square', - 'bitbucket', - 'bitbucket-square', - 'bitcoin', - 'black-tie', - 'bluetooth', - 'bluetooth-b', - 'btc', - 'buysellads', - 'cc-amex', - 'cc-diners-club', - 'cc-discover', - 'cc-jcb', - 'cc-mastercard', - 'cc-paypal', - 'cc-stripe', - 'cc-visa', - 'chrome', - 'codepen', - 'codiepie', - 'connectdevelop', - 'contao', - 'css3', - 'dashcube', - 'delicious', - 'deviantart', - 'digg', - 'dribbble', - 'dropbox', - 'drupal', - 'edge', - 'eercast', - 'empire', - 'envira', - 'etsy', - 'expeditedssl', - 'fa', - 'facebook', - 'facebook-f', - 'facebook-official', - 'facebook-square', - 'firefox', - 'first-order', - 'flickr', - 'font-awesome', - 'fonticons', - 'fort-awesome', - 'forumbee', - 'foursquare', - 'free-code-camp', - 'ge', - 'get-pocket', - 'gg', - 'gg-circle', - 'git', - 'git-square', - 'github', - 'github-alt', - 'github-square', - 'gitlab', - 'gittip', - 'glide', - 'glide-g', - 'google', - 'google-plus', - 'google-plus-circle', - 'google-plus-official', - 'google-plus-square', - 'google-wallet', - 'gratipay', - 'grav', - 'hacker-news', - 'houzz', - 'html5', - 'imdb', - 'instagram', - 'internet-explorer', - 'ioxhost', - 'joomla', - 'jsfiddle', - 'lastfm', - 'lastfm-square', - 'leanpub', - 'linkedin', - 'linkedin-square', - 'linode', - 'linux', - 'maxcdn', - 'meanpath', - 'medium', - 'meetup', - 'mixcloud', - 'modx', - 'odnoklassniki', - 'odnoklassniki-square', - 'opencart', - 'openid', - 'opera', - 'optin-monster', - 'pagelines', - 'paypal', - 'pied-piper', - 'pied-piper-alt', - 'pied-piper-pp', - 'pinterest', - 'pinterest-p', - 'pinterest-square', - 'product-hunt', - 'qq', - 'quora', - 'ra', - 'ravelry', - 'rebel', - 'reddit', - 'reddit-alien', - 'reddit-square', - 'renren', - 'resistance', - 'safari', - 'scribd', - 'sellsy', - 'share-alt', - 'share-alt-square', - 'shirtsinbulk', - 'simplybuilt', - 'skyatlas', - 'skype', - 'slack', - 'slideshare', - 'snapchat', - 'snapchat-ghost', - 'snapchat-square', - 'soundcloud', - 'spotify', - 'stack-exchange', - 'stack-overflow', - 'steam', - 'steam-square', - 'stumbleupon', - 'stumbleupon-circle', - 'superpowers', - 'telegram', - 'tencent-weibo', - 'themeisle', - 'trello', - 'tripadvisor', - 'tumblr', - 'tumblr-square', - 'twitch', - 'twitter', - 'twitter-square', - 'usb', - 'viacoin', - 'viadeo', - 'viadeo-square', - 'vimeo', - 'vimeo-square', - 'vine', - 'vk', - 'wechat', - 'weibo', - 'weixin', - 'whatsapp', - 'wikipedia-w', - 'windows', - 'wordpress', - 'wpbeginner', - 'wpexplorer', - 'wpforms', - 'xing', - 'xing-square', - 'y-combinator', - 'y-combinator-square', - 'yahoo', - 'yc', - 'yc-square', - 'yelp', - 'yoast', - 'youtube', - 'youtube-play', - 'youtube-square' - ] - }, - { - title: '医疗', - icon: [ - 'ambulance', - 'h-square', - 'heart', - 'heart-o', - 'heartbeat', - 'hospital-o', - 'medkit', - 'plus-square', - 'stethoscope', - 'user-md', - 'wheelchair', - 'wheelchair-alt' - ] - } -] diff --git a/src/views/demo/components/icon/icon-svg.vue b/src/views/demo/components/icon/icon-svg.vue deleted file mode 100644 index f55091cd..00000000 --- a/src/views/demo/components/icon/icon-svg.vue +++ /dev/null @@ -1,42 +0,0 @@ - - - diff --git a/src/views/demo/components/icon/icon.vue b/src/views/demo/components/icon/icon.vue deleted file mode 100644 index ba4eb5c7..00000000 --- a/src/views/demo/components/icon/icon.vue +++ /dev/null @@ -1,22 +0,0 @@ - - - diff --git a/src/views/demo/components/icon/list.vue b/src/views/demo/components/icon/list.vue deleted file mode 100644 index df9ed473..00000000 --- a/src/views/demo/components/icon/list.vue +++ /dev/null @@ -1,46 +0,0 @@ - - - diff --git a/src/views/demo/components/icon/select-svg.vue b/src/views/demo/components/icon/select-svg.vue deleted file mode 100644 index 6c3ecd76..00000000 --- a/src/views/demo/components/icon/select-svg.vue +++ /dev/null @@ -1,24 +0,0 @@ - - - diff --git a/src/views/demo/components/icon/select.vue b/src/views/demo/components/icon/select.vue deleted file mode 100644 index 138c4e9d..00000000 --- a/src/views/demo/components/icon/select.vue +++ /dev/null @@ -1,56 +0,0 @@ - - - - - diff --git a/src/views/demo/components/index/index.vue b/src/views/demo/components/index/index.vue deleted file mode 100644 index 62126807..00000000 --- a/src/views/demo/components/index/index.vue +++ /dev/null @@ -1,21 +0,0 @@ - - - diff --git a/src/views/demo/components/json-tree/index.vue b/src/views/demo/components/json-tree/index.vue deleted file mode 100644 index cd9c16d8..00000000 --- a/src/views/demo/components/json-tree/index.vue +++ /dev/null @@ -1,24 +0,0 @@ - - - diff --git a/src/views/demo/components/layout/grid.vue b/src/views/demo/components/layout/grid.vue deleted file mode 100644 index 875aa7bb..00000000 --- a/src/views/demo/components/layout/grid.vue +++ /dev/null @@ -1,122 +0,0 @@ - - - - - diff --git a/src/views/demo/components/layout/splitpane.vue b/src/views/demo/components/layout/splitpane.vue deleted file mode 100644 index eb07a75c..00000000 --- a/src/views/demo/components/layout/splitpane.vue +++ /dev/null @@ -1,37 +0,0 @@ - - - diff --git a/src/views/demo/components/markdown/md/doc.md b/src/views/demo/components/markdown/md/doc.md deleted file mode 100644 index 189e9773..00000000 --- a/src/views/demo/components/markdown/md/doc.md +++ /dev/null @@ -1,38 +0,0 @@ -# 一级标题 - -| ID | Name | Email | -| --- | --- | --- | -| 0001 | FairyEver | 1711467488@qq.com | - -``` -// 注释 -[].forEach.call($$("*"), a => { - a.style.outline="1px solid #"+(~~(Math.random()*(1<<24))).toString(16) -}) -``` - -``` -
-

Hello World

-
-``` - -``` -body { - background-color: #333; -} -``` - -一般引用 - -> 引用文字 - -分享一个我很早前的一副设计作品 [in Lofter](http://fairyever.lofter.com/post/16ff00_6796fe8) 借此演示百度云链接的显示优化 - -> https://pan.baidu.com/s/1kW6uUwB - -设计源文件 - -> 链接: https://pan.baidu.com/s/1ggFW21l 密码: 877y - -[https://github.com/d2-projects](https://github.com/d2-projects) \ No newline at end of file diff --git a/src/views/demo/components/markdown/source.vue b/src/views/demo/components/markdown/source.vue deleted file mode 100644 index 0a4bda98..00000000 --- a/src/views/demo/components/markdown/source.vue +++ /dev/null @@ -1,17 +0,0 @@ - - - diff --git a/src/views/demo/components/markdown/url.vue b/src/views/demo/components/markdown/url.vue deleted file mode 100644 index 49461394..00000000 --- a/src/views/demo/components/markdown/url.vue +++ /dev/null @@ -1,6 +0,0 @@ - diff --git a/src/views/demo/playground/add-routes/alternates/1.vue b/src/views/demo/playground/add-routes/alternates/1.vue deleted file mode 100644 index f99165a0..00000000 --- a/src/views/demo/playground/add-routes/alternates/1.vue +++ /dev/null @@ -1,5 +0,0 @@ - diff --git a/src/views/demo/playground/add-routes/alternates/2.vue b/src/views/demo/playground/add-routes/alternates/2.vue deleted file mode 100644 index e03c9f47..00000000 --- a/src/views/demo/playground/add-routes/alternates/2.vue +++ /dev/null @@ -1,5 +0,0 @@ - diff --git a/src/views/demo/playground/add-routes/alternates/3.vue b/src/views/demo/playground/add-routes/alternates/3.vue deleted file mode 100644 index 47670bc1..00000000 --- a/src/views/demo/playground/add-routes/alternates/3.vue +++ /dev/null @@ -1,5 +0,0 @@ - diff --git a/src/views/demo/playground/add-routes/routes.vue b/src/views/demo/playground/add-routes/routes.vue deleted file mode 100644 index 1f18e316..00000000 --- a/src/views/demo/playground/add-routes/routes.vue +++ /dev/null @@ -1,109 +0,0 @@ - - - diff --git a/src/views/demo/playground/db/all/index.vue b/src/views/demo/playground/db/all/index.vue deleted file mode 100644 index d5722d1d..00000000 --- a/src/views/demo/playground/db/all/index.vue +++ /dev/null @@ -1,33 +0,0 @@ - - - diff --git a/src/views/demo/playground/db/page-public/index.vue b/src/views/demo/playground/db/page-public/index.vue deleted file mode 100644 index 69c8f1b5..00000000 --- a/src/views/demo/playground/db/page-public/index.vue +++ /dev/null @@ -1,127 +0,0 @@ - - - diff --git a/src/views/demo/playground/db/page-snapshot-public/index.vue b/src/views/demo/playground/db/page-snapshot-public/index.vue deleted file mode 100644 index 48a5c337..00000000 --- a/src/views/demo/playground/db/page-snapshot-public/index.vue +++ /dev/null @@ -1,114 +0,0 @@ - - - diff --git a/src/views/demo/playground/db/page-snapshot-user/index.vue b/src/views/demo/playground/db/page-snapshot-user/index.vue deleted file mode 100644 index d59dc958..00000000 --- a/src/views/demo/playground/db/page-snapshot-user/index.vue +++ /dev/null @@ -1,114 +0,0 @@ - - - diff --git a/src/views/demo/playground/db/page-user/index.vue b/src/views/demo/playground/db/page-user/index.vue deleted file mode 100644 index 0283872d..00000000 --- a/src/views/demo/playground/db/page-user/index.vue +++ /dev/null @@ -1,139 +0,0 @@ - - - diff --git a/src/views/demo/playground/db/public/index.vue b/src/views/demo/playground/db/public/index.vue deleted file mode 100644 index 576b7ea5..00000000 --- a/src/views/demo/playground/db/public/index.vue +++ /dev/null @@ -1,123 +0,0 @@ - - - diff --git a/src/views/demo/playground/db/user/index.vue b/src/views/demo/playground/db/user/index.vue deleted file mode 100644 index bd523433..00000000 --- a/src/views/demo/playground/db/user/index.vue +++ /dev/null @@ -1,125 +0,0 @@ - - - diff --git a/src/views/demo/playground/env/index.vue b/src/views/demo/playground/env/index.vue deleted file mode 100644 index 66bb400a..00000000 --- a/src/views/demo/playground/env/index.vue +++ /dev/null @@ -1,16 +0,0 @@ - - - diff --git a/src/views/demo/playground/frame/d2-doc/index.vue b/src/views/demo/playground/frame/d2-doc/index.vue deleted file mode 100644 index 82e9b26b..00000000 --- a/src/views/demo/playground/frame/d2-doc/index.vue +++ /dev/null @@ -1,3 +0,0 @@ - diff --git a/src/views/demo/playground/frame/html/index.vue b/src/views/demo/playground/frame/html/index.vue deleted file mode 100644 index 8c4bafc9..00000000 --- a/src/views/demo/playground/frame/html/index.vue +++ /dev/null @@ -1,3 +0,0 @@ - diff --git a/src/views/demo/playground/frame/report/index.vue b/src/views/demo/playground/frame/report/index.vue deleted file mode 100644 index d1867ff6..00000000 --- a/src/views/demo/playground/frame/report/index.vue +++ /dev/null @@ -1,3 +0,0 @@ - diff --git a/src/views/demo/playground/index/index.vue b/src/views/demo/playground/index/index.vue deleted file mode 100644 index 204fddf1..00000000 --- a/src/views/demo/playground/index/index.vue +++ /dev/null @@ -1,21 +0,0 @@ - - - diff --git a/src/views/demo/playground/locales/index.vue b/src/views/demo/playground/locales/index.vue deleted file mode 100644 index d7da8fe5..00000000 --- a/src/views/demo/playground/locales/index.vue +++ /dev/null @@ -1,22 +0,0 @@ - diff --git a/src/views/demo/playground/log/ajax/index.vue b/src/views/demo/playground/log/ajax/index.vue deleted file mode 100644 index 1e3fd621..00000000 --- a/src/views/demo/playground/log/ajax/index.vue +++ /dev/null @@ -1,20 +0,0 @@ - - - diff --git a/src/views/demo/playground/log/console/image/demo.png b/src/views/demo/playground/log/console/image/demo.png deleted file mode 100644 index 35a5c716cffd640daf38b058ac428e434cd440bc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 66362 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 SZyWdw_>&Ts7poF64ER4&Oqm)0 diff --git a/src/views/demo/playground/log/console/index.vue b/src/views/demo/playground/log/console/index.vue deleted file mode 100644 index d23b74ad..00000000 --- a/src/views/demo/playground/log/console/index.vue +++ /dev/null @@ -1,67 +0,0 @@ - - - - - diff --git a/src/views/demo/playground/log/error/index.vue b/src/views/demo/playground/log/error/index.vue deleted file mode 100644 index 383c3acb..00000000 --- a/src/views/demo/playground/log/error/index.vue +++ /dev/null @@ -1,18 +0,0 @@ - - - diff --git a/src/views/demo/playground/log/log/index.vue b/src/views/demo/playground/log/log/index.vue deleted file mode 100644 index 04f14e43..00000000 --- a/src/views/demo/playground/log/log/index.vue +++ /dev/null @@ -1,28 +0,0 @@ - - - diff --git a/src/views/demo/playground/page-argu/get.vue b/src/views/demo/playground/page-argu/get.vue deleted file mode 100644 index 4e49d6d5..00000000 --- a/src/views/demo/playground/page-argu/get.vue +++ /dev/null @@ -1,16 +0,0 @@ - - - diff --git a/src/views/demo/playground/page-argu/send.vue b/src/views/demo/playground/page-argu/send.vue deleted file mode 100644 index 4bd55e79..00000000 --- a/src/views/demo/playground/page-argu/send.vue +++ /dev/null @@ -1,55 +0,0 @@ - - - diff --git a/src/views/demo/playground/page-cache/off.vue b/src/views/demo/playground/page-cache/off.vue deleted file mode 100644 index 03d19b81..00000000 --- a/src/views/demo/playground/page-cache/off.vue +++ /dev/null @@ -1,17 +0,0 @@ - - - diff --git a/src/views/demo/playground/page-cache/on.vue b/src/views/demo/playground/page-cache/on.vue deleted file mode 100644 index 972dfe93..00000000 --- a/src/views/demo/playground/page-cache/on.vue +++ /dev/null @@ -1,18 +0,0 @@ - - - diff --git a/src/views/demo/playground/page-cache/params.vue b/src/views/demo/playground/page-cache/params.vue deleted file mode 100644 index ddd44f9f..00000000 --- a/src/views/demo/playground/page-cache/params.vue +++ /dev/null @@ -1,42 +0,0 @@ - - - diff --git a/src/views/demo/playground/store/fullscreen/index.vue b/src/views/demo/playground/store/fullscreen/index.vue deleted file mode 100644 index a8b59b77..00000000 --- a/src/views/demo/playground/store/fullscreen/index.vue +++ /dev/null @@ -1,19 +0,0 @@ - - - diff --git a/src/views/demo/playground/store/gray/index.vue b/src/views/demo/playground/store/gray/index.vue deleted file mode 100644 index 04285eab..00000000 --- a/src/views/demo/playground/store/gray/index.vue +++ /dev/null @@ -1,87 +0,0 @@ - - - - - diff --git a/src/views/demo/playground/store/menu/index.vue b/src/views/demo/playground/store/menu/index.vue deleted file mode 100644 index c447dd28..00000000 --- a/src/views/demo/playground/store/menu/index.vue +++ /dev/null @@ -1,148 +0,0 @@ - - - diff --git a/src/views/demo/playground/store/page/index.vue b/src/views/demo/playground/store/page/index.vue deleted file mode 100644 index 591344cc..00000000 --- a/src/views/demo/playground/store/page/index.vue +++ /dev/null @@ -1,98 +0,0 @@ - - - diff --git a/src/views/demo/playground/store/size/index.vue b/src/views/demo/playground/store/size/index.vue deleted file mode 100644 index ab853410..00000000 --- a/src/views/demo/playground/store/size/index.vue +++ /dev/null @@ -1,39 +0,0 @@ - - - diff --git a/src/views/demo/playground/store/theme/index.vue b/src/views/demo/playground/store/theme/index.vue deleted file mode 100644 index 672513ae..00000000 --- a/src/views/demo/playground/store/theme/index.vue +++ /dev/null @@ -1,74 +0,0 @@ - - - - - diff --git a/src/views/demo/playground/store/transition/index.vue b/src/views/demo/playground/store/transition/index.vue deleted file mode 100644 index f74f3d42..00000000 --- a/src/views/demo/playground/store/transition/index.vue +++ /dev/null @@ -1,26 +0,0 @@ - - - diff --git a/src/views/demo/playground/store/ua/index.vue b/src/views/demo/playground/store/ua/index.vue deleted file mode 100644 index 700f15f4..00000000 --- a/src/views/demo/playground/store/ua/index.vue +++ /dev/null @@ -1,23 +0,0 @@ - - - diff --git a/src/views/demo/plugins/clipboard-polyfill/index.vue b/src/views/demo/plugins/clipboard-polyfill/index.vue deleted file mode 100644 index a9f8f662..00000000 --- a/src/views/demo/plugins/clipboard-polyfill/index.vue +++ /dev/null @@ -1,82 +0,0 @@ - - - diff --git a/src/views/demo/plugins/day/index.vue b/src/views/demo/plugins/day/index.vue deleted file mode 100644 index 534bcc57..00000000 --- a/src/views/demo/plugins/day/index.vue +++ /dev/null @@ -1,73 +0,0 @@ - - - diff --git a/src/views/demo/plugins/export/table.vue b/src/views/demo/plugins/export/table.vue deleted file mode 100644 index 4757fe73..00000000 --- a/src/views/demo/plugins/export/table.vue +++ /dev/null @@ -1,72 +0,0 @@ - - - diff --git a/src/views/demo/plugins/export/txt.vue b/src/views/demo/plugins/export/txt.vue deleted file mode 100644 index a06c15cf..00000000 --- a/src/views/demo/plugins/export/txt.vue +++ /dev/null @@ -1,47 +0,0 @@ - - - diff --git a/src/views/demo/plugins/import/csv.vue b/src/views/demo/plugins/import/csv.vue deleted file mode 100644 index 2e3c09f8..00000000 --- a/src/views/demo/plugins/import/csv.vue +++ /dev/null @@ -1,62 +0,0 @@ - - - diff --git a/src/views/demo/plugins/import/xlsx.vue b/src/views/demo/plugins/import/xlsx.vue deleted file mode 100644 index 97cbfb18..00000000 --- a/src/views/demo/plugins/import/xlsx.vue +++ /dev/null @@ -1,64 +0,0 @@ - - - diff --git a/src/views/demo/plugins/index/index.vue b/src/views/demo/plugins/index/index.vue deleted file mode 100644 index 97b4dba1..00000000 --- a/src/views/demo/plugins/index/index.vue +++ /dev/null @@ -1,21 +0,0 @@ - - - diff --git a/src/views/demo/plugins/js-cookie/index.vue b/src/views/demo/plugins/js-cookie/index.vue deleted file mode 100644 index a1db081f..00000000 --- a/src/views/demo/plugins/js-cookie/index.vue +++ /dev/null @@ -1,54 +0,0 @@ - - -