refactor: remove old demo pages and static menu logic
1. 删除大量旧的示例页面、组件示例和静态菜单配置 2. 新增菜单扁平数组转树形结构工具函数 3. 重构菜单加载逻辑,改为从后端动态获取并格式化 4. 新增全局权限检查方法和自定义权限指令 5. 优化侧边栏菜单路由跳转逻辑,自动跳转第一个有权限的子页面 6. 移除路由中对旧demo模块的引用
This commit is contained in:
601
docs/menu-permission-migration.md
Normal file
601
docs/menu-permission-migration.md
Normal file
@@ -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
|
||||
<el-button v-permission="'/system_settings/user_management/user'">新增用户</el-button>
|
||||
```
|
||||
|
||||
### 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'`,用于控制错误日志是否弹出提示。
|
||||
@@ -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'
|
||||
})
|
||||
}
|
||||
13
src/api/menu.js
Normal file
13
src/api/menu.js
Normal file
@@ -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
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 标题
|
||||
|
||||
29
src/main.js
29
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')
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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' }
|
||||
]
|
||||
}
|
||||
@@ -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' }
|
||||
]
|
||||
}
|
||||
@@ -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' }
|
||||
]
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
@@ -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渲染' } }
|
||||
]
|
||||
}
|
||||
@@ -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 中文文档' } }
|
||||
]
|
||||
}
|
||||
@@ -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' } }
|
||||
]
|
||||
}
|
||||
@@ -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-')
|
||||
}
|
||||
@@ -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
|
||||
]
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,104 +0,0 @@
|
||||
<template>
|
||||
<d2-container
|
||||
ref="container"
|
||||
:type="containerType"
|
||||
:better-scroll="betterScroll"
|
||||
:scroll-delay="scrollDelay"
|
||||
@scroll="({x, y}) => { scrollTop = y }">
|
||||
<template slot="header">
|
||||
<el-form
|
||||
:inline="true"
|
||||
size="mini">
|
||||
<el-form-item
|
||||
label="布局类型"
|
||||
class="d2-mb-0">
|
||||
<el-radio-group v-model="containerType">
|
||||
<el-radio-button label="full"></el-radio-button>
|
||||
<el-radio-button label="card"></el-radio-button>
|
||||
<el-radio-button label="ghost"></el-radio-button>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label="滚动距离"
|
||||
class="d2-mb-0">
|
||||
<el-input
|
||||
:value="scrollTop"
|
||||
style="width: 130px;">
|
||||
<template slot="append">px</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-if="!betterScroll"
|
||||
label="事件延迟(ms)"
|
||||
class="d2-mb-0">
|
||||
<el-input-number
|
||||
v-model="scrollDelay"
|
||||
:min="10"
|
||||
:max="2000"
|
||||
:step="100"
|
||||
style="width: 110px;"/>
|
||||
</el-form-item>
|
||||
<el-form-item class="d2-mb-0">
|
||||
<el-button
|
||||
v-if="scrollTop >= 55"
|
||||
type="primary"
|
||||
@click="$refs.container.scrollToTop">
|
||||
回到顶部
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</template>
|
||||
<el-alert
|
||||
type="success"
|
||||
:title="`${betterScroll ? '此示例开启了 BetterScroll ' : ''}请向下滚动`"
|
||||
class="d2-mb-10"
|
||||
center/>
|
||||
<d2-demo-article
|
||||
v-for="i in 10"
|
||||
:key="i"
|
||||
:style="articleStyle"
|
||||
long/>
|
||||
<el-form
|
||||
slot="footer"
|
||||
:inline="true"
|
||||
size="mini">
|
||||
<el-form-item class="d2-mb-0">
|
||||
<el-button @click="$refs.container.scrollBy(0, 30)">相对滚动 (0, 30) 像素</el-button>
|
||||
</el-form-item>
|
||||
<el-form-item class="d2-mb-0">
|
||||
<el-button @click="$refs.container.scrollTo(0, 100)">滚动到 (0, 100) 像素位置</el-button>
|
||||
</el-form-item>
|
||||
<el-form-item class="d2-mb-0">
|
||||
<el-button @click="$refs.container.scrollTop(100)">滚动到垂直位置 100</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</d2-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import d2DemoArticle from './components/d2-demo-article'
|
||||
export default {
|
||||
components: {
|
||||
'd2-demo-article': d2DemoArticle
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
containerType: 'full',
|
||||
scrollDelay: 10,
|
||||
scrollTop: 0
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
// 是否开启 better scroll
|
||||
betterScroll () {
|
||||
return this.$route.query.bs === 'true'
|
||||
},
|
||||
// 根据滚动位置返回文章的样式
|
||||
articleStyle () {
|
||||
return {
|
||||
opacity: this.scrollTop > 55 ? '1' : '.1'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,16 +0,0 @@
|
||||
<template>
|
||||
<d2-container type="card" better-scroll>
|
||||
<template slot="header">Header</template>
|
||||
<d2-demo-article/>
|
||||
<template slot="footer">Footer</template>
|
||||
</d2-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import d2DemoArticle from './components/d2-demo-article'
|
||||
export default {
|
||||
components: {
|
||||
'd2-demo-article': d2DemoArticle
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,16 +0,0 @@
|
||||
<template>
|
||||
<d2-container type="card">
|
||||
<template slot="header">Header</template>
|
||||
<d2-demo-article/>
|
||||
<template slot="footer">Footer</template>
|
||||
</d2-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import d2DemoArticle from './components/d2-demo-article'
|
||||
export default {
|
||||
components: {
|
||||
'd2-demo-article': d2DemoArticle
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,14 +0,0 @@
|
||||
<template>
|
||||
<d2-container type="card">
|
||||
<d2-demo-article/>
|
||||
</d2-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import d2DemoArticle from './components/d2-demo-article'
|
||||
export default {
|
||||
components: {
|
||||
'd2-demo-article': d2DemoArticle
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,50 +0,0 @@
|
||||
<template>
|
||||
<div class="d2-demo-article">
|
||||
<div v-if="!long" class="d2-demo-article__control">
|
||||
<el-switch
|
||||
v-model="isLong"
|
||||
active-text="长内容"
|
||||
inactive-text="短内容"/>
|
||||
</div>
|
||||
<d2-markdown v-show="isLong" :source="sourceLong"/>
|
||||
<d2-markdown v-show="!isLong" :source="sourceShort"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import sourceLong from '../md/long.md'
|
||||
import sourceShort from '../md/short.md'
|
||||
export default {
|
||||
props: {
|
||||
// 指定为长文本
|
||||
long: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
sourceLong,
|
||||
sourceShort,
|
||||
isLong: false
|
||||
}
|
||||
},
|
||||
created () {
|
||||
this.isLong = this.long
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.d2-demo-article {
|
||||
transition: opacity .3s;
|
||||
.d2-demo-article__control {
|
||||
padding: 8px 16px;
|
||||
margin-bottom: 10px;
|
||||
box-sizing: border-box;
|
||||
border-radius: 4px;
|
||||
background-color: #f4f4f5;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,16 +0,0 @@
|
||||
<template>
|
||||
<d2-container better-scroll>
|
||||
<template slot="header">Header</template>
|
||||
<d2-demo-article/>
|
||||
<template slot="footer">Header</template>
|
||||
</d2-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import d2DemoArticle from './components/d2-demo-article'
|
||||
export default {
|
||||
components: {
|
||||
'd2-demo-article': d2DemoArticle
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,16 +0,0 @@
|
||||
<template>
|
||||
<d2-container>
|
||||
<template slot="header">Header</template>
|
||||
<d2-demo-article/>
|
||||
<template slot="footer">Footer</template>
|
||||
</d2-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import d2DemoArticle from './components/d2-demo-article'
|
||||
export default {
|
||||
components: {
|
||||
'd2-demo-article': d2DemoArticle
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,14 +0,0 @@
|
||||
<template>
|
||||
<d2-container>
|
||||
<d2-demo-article/>
|
||||
</d2-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import d2DemoArticle from './components/d2-demo-article'
|
||||
export default {
|
||||
components: {
|
||||
'd2-demo-article': d2DemoArticle
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,20 +0,0 @@
|
||||
<template>
|
||||
<d2-container type="ghost" better-scroll>
|
||||
<template slot="header">Header</template>
|
||||
<div class="d2-pt d2-pb">
|
||||
<el-card shadow="never" class="d2-card" style="width: 400px;">
|
||||
<d2-demo-article/>
|
||||
</el-card>
|
||||
</div>
|
||||
<template slot="footer">Footer</template>
|
||||
</d2-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import d2DemoArticle from './components/d2-demo-article'
|
||||
export default {
|
||||
components: {
|
||||
'd2-demo-article': d2DemoArticle
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,20 +0,0 @@
|
||||
<template>
|
||||
<d2-container type="ghost">
|
||||
<template slot="header">Header</template>
|
||||
<div class="d2-pt d2-pb">
|
||||
<el-card shadow="never" class="d2-card" style="width: 400px;">
|
||||
<d2-demo-article/>
|
||||
</el-card>
|
||||
</div>
|
||||
<template slot="footer">Footer</template>
|
||||
</d2-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import d2DemoArticle from './components/d2-demo-article'
|
||||
export default {
|
||||
components: {
|
||||
'd2-demo-article': d2DemoArticle
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,18 +0,0 @@
|
||||
<template>
|
||||
<d2-container type="ghost">
|
||||
<div class="d2-pt d2-pb">
|
||||
<el-card shadow="never" class="d2-card" style="width: 400px;">
|
||||
<d2-demo-article/>
|
||||
</el-card>
|
||||
</div>
|
||||
</d2-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import d2DemoArticle from './components/d2-demo-article'
|
||||
export default {
|
||||
components: {
|
||||
'd2-demo-article': d2DemoArticle
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -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
|
||||
|
||||
- 用户决策:根据场景可给予用户操作建议或安全提示,但不能代替用户进行决策;
|
||||
|
||||
- 结果可控:用户可以自由的进行操作,包括撤销、回退和终止当前操作等。
|
||||
@@ -1,17 +0,0 @@
|
||||
## vue.js
|
||||
|
||||
**易用**
|
||||
|
||||
已经会了 HTML、CSS、JavaScript?即刻阅读指南开始构建应用!
|
||||
|
||||
**灵活**
|
||||
|
||||
不断繁荣的生态系统,可以在一个库和一套完整框架之间自如伸缩。
|
||||
|
||||
**高效**
|
||||
|
||||
20kB min+gzip 运行大小
|
||||
|
||||
超快虚拟 DOM
|
||||
|
||||
最省心的优化
|
||||
@@ -1,94 +0,0 @@
|
||||
<template>
|
||||
<d2-container type="card" class="page">
|
||||
<template slot="header">数字动画组件</template>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="6">
|
||||
<el-card shadow="never" class="d2-card d2-mb">
|
||||
<p slot="title">只设置目标数字</p>
|
||||
<div class="group">
|
||||
<d2-count-up :end="100"/>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-card shadow="never" class="d2-card d2-mb">
|
||||
<p slot="title">设置起止数值</p>
|
||||
<div class="group">
|
||||
<d2-count-up :start="14" :end="100"/>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-card shadow="never" class="d2-card d2-mb">
|
||||
<p slot="title">小数位数</p>
|
||||
<div class="group">
|
||||
<d2-count-up :end="100" :decimals="2"/>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-card shadow="never" class="d2-card d2-mb">
|
||||
<p slot="title">动画时长</p>
|
||||
<div class="group">
|
||||
<d2-count-up :end="100" :duration="6"/>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-card shadow="never" class="d2-card">
|
||||
<p slot="title">回调函数</p>
|
||||
<div class="group">
|
||||
<d2-count-up :end="100" :callback="() => {className = 'end'}" :class="className"/>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-card shadow="never" class="d2-card d2-mb-0">
|
||||
<p slot="title">结束一秒后更新数值</p>
|
||||
<div class="group">
|
||||
<d2-count-up :end="end" :callback="update"/>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</d2-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
// 回调函数使用
|
||||
className: '',
|
||||
// 更新数值用
|
||||
end: 50
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
update () {
|
||||
setTimeout(() => {
|
||||
this.end = 100
|
||||
}, 1000)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.page {
|
||||
.group {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
span {
|
||||
font-size: 60px;
|
||||
&.end {
|
||||
padding: 0px 20px;
|
||||
border-radius: 4px;
|
||||
background-color: $color-success;
|
||||
color: #FFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,49 +0,0 @@
|
||||
<template>
|
||||
<d2-container>
|
||||
<d2-quill
|
||||
style="min-height: 200px; margin-bottom: 20px;"
|
||||
v-model="value"
|
||||
@text-change="textChangeHandler"
|
||||
@selection-change="selectionChangeHandler"
|
||||
@editor-change="editorChangeHandler"/>
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="handleAddRow">
|
||||
添加一行
|
||||
</el-button>
|
||||
<el-card shadow="never" class="d2-card d2-mt">
|
||||
<d2-highlight :code="value" format-html/>
|
||||
</el-card>
|
||||
</d2-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import value from './value'
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
value
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleAddRow () {
|
||||
this.value += '<p style="color: #409EFF;">我是新增的行</p>'
|
||||
},
|
||||
textChangeHandler (delta, oldDelta, source) {
|
||||
// console.group('QuillEditor textChangeHandler')
|
||||
// console.log(delta, oldDelta, source)
|
||||
// console.groupEnd()
|
||||
},
|
||||
selectionChangeHandler (range, oldRange, source) {
|
||||
// console.group('QuillEditor selectionChangeHandler')
|
||||
// console.log(range, oldRange, source)
|
||||
// console.groupEnd()
|
||||
},
|
||||
editorChangeHandler (eventName, ...args) {
|
||||
// console.group('QuillEditor editorChangeHandler')
|
||||
// console.log(eventName, args)
|
||||
// console.groupEnd()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,6 +0,0 @@
|
||||
export default `<p>
|
||||
<a href="https://github.com/d2-projects/d2-admin" target="_blank" class="ql-size-large" style="color: rgb(65, 184, 131);"><strong>D2 Admin</strong></a>
|
||||
<strong style="color: rgb(65, 184, 131);"></strong>
|
||||
by
|
||||
<a href="https://cn.vuejs.org/" target="_blank" class="ql-size-large" style="color: rgb(65, 184, 131);"><strong>vue.js</strong></a>
|
||||
</p>`
|
||||
@@ -1,33 +0,0 @@
|
||||
<template>
|
||||
<d2-container type="card">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="14">
|
||||
<d2-ueditor v-model="text"/>
|
||||
</el-col>
|
||||
<el-col :span="10">
|
||||
<el-card v-if="text" shadow="never" style="border: 1px solid #d4d4d4;">
|
||||
<template slot="header">Result</template>
|
||||
<div v-html="text" style="margin: -20px 0px;"></div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<template slot="footer">
|
||||
<el-button type="primary" @click="text += text">
|
||||
<d2-icon name="copy"/> 当前内容 x2
|
||||
</el-button>
|
||||
<el-button type="danger" @click="text = ''">
|
||||
<d2-icon name="trash-o"/> 清空
|
||||
</el-button>
|
||||
</template>
|
||||
</d2-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
text: '<p>Hello World</p>'
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,8 +0,0 @@
|
||||
export default `body {
|
||||
background-color: aliceblue;
|
||||
height: 100%;
|
||||
}
|
||||
.my-card {
|
||||
height: 300px;
|
||||
width: 300px;
|
||||
}`
|
||||
@@ -1,8 +0,0 @@
|
||||
export default `<ul>
|
||||
<li class="li-1"><p>Hello</p></li>
|
||||
<li>
|
||||
<span style="color: red;">
|
||||
Hello
|
||||
</span>
|
||||
</li>
|
||||
</ul>`
|
||||
@@ -1,3 +0,0 @@
|
||||
export default `[].forEach.call($$("*"), a => {
|
||||
a.style.outline="1px solid #"+(~~(Math.random()*(1<<24))).toString(16)
|
||||
})`
|
||||
@@ -1,8 +0,0 @@
|
||||
export default `body {
|
||||
background-color: aliceblue;
|
||||
height: 100%;
|
||||
.my-card {
|
||||
height: 300px;
|
||||
width: 300px;
|
||||
}
|
||||
}`
|
||||
@@ -1,38 +0,0 @@
|
||||
<template>
|
||||
<d2-container>
|
||||
<template slot="header">代码高亮组件</template>
|
||||
<el-card shadow="never" class="d2-mb">
|
||||
<p slot="title">javascript</p>
|
||||
<d2-highlight :code="codeJavascript"/>
|
||||
</el-card>
|
||||
<el-card shadow="never" class="d2-mb">
|
||||
<p slot="title">css</p>
|
||||
<d2-highlight :code="codeCSS"/>
|
||||
</el-card>
|
||||
<el-card shadow="never" class="d2-mb">
|
||||
<p slot="title">scss</p>
|
||||
<d2-highlight :code="codeSCSS"/>
|
||||
</el-card>
|
||||
<el-card shadow="never">
|
||||
<p slot="title">html</p>
|
||||
<d2-highlight :code="codeHTML"/>
|
||||
</el-card>
|
||||
</d2-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import codeJavascript from './code/javascript'
|
||||
import codeCSS from './code/css'
|
||||
import codeSCSS from './code/scss'
|
||||
import codeHTML from './code/html'
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
codeJavascript,
|
||||
codeCSS,
|
||||
codeSCSS,
|
||||
codeHTML
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,82 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-popover
|
||||
ref="pop"
|
||||
placement="right"
|
||||
:title="icon"
|
||||
width="300"
|
||||
trigger="click">
|
||||
<div class="icon-group">
|
||||
<i :class="'fa fa-' + icon"></i>
|
||||
</div>
|
||||
<el-row :gutter="10">
|
||||
<el-col :span="8">
|
||||
<el-tooltip effect="dark" :content="iconClass" placement="top">
|
||||
<el-button @click="copy(iconClass)" style="width: 100%;">Class</el-button>
|
||||
</el-tooltip>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-tooltip effect="dark" :content="iconHtml" placement="top">
|
||||
<el-button @click="copy(iconHtml)" style="width: 100%;">HTML</el-button>
|
||||
</el-tooltip>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-tooltip effect="dark" :content="iconComponent" placement="top">
|
||||
<el-button @click="copy(iconComponent)" style="width: 100%;">组件</el-button>
|
||||
</el-tooltip>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-popover>
|
||||
<span v-popover:pop>
|
||||
<el-tag type="info" class="icon-tag">
|
||||
<i :class="'fa fa-' + icon"></i>
|
||||
</el-tag>
|
||||
<span style="font-size: 10px;">{{icon}}</span>
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as clipboard from 'clipboard-polyfill'
|
||||
export default {
|
||||
props: {
|
||||
icon: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
iconClass () {
|
||||
return `fa fa-${this.icon}`
|
||||
},
|
||||
iconHtml () {
|
||||
return `<i class="fa fa-${this.icon}" aria-hidden="true"></i>`
|
||||
},
|
||||
iconComponent () {
|
||||
return `<d2-icon name="${this.icon}"/>`
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
copy (text) {
|
||||
clipboard.writeText(text)
|
||||
this.$message({
|
||||
message: `${text} 复制到剪贴板`,
|
||||
type: 'success'
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.icon-group {
|
||||
text-align: center;
|
||||
font-size: 200px;
|
||||
}
|
||||
.icon-tag {
|
||||
width: 32px;
|
||||
text-align: center;
|
||||
margin-right: 5px;
|
||||
}
|
||||
</style>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,42 +0,0 @@
|
||||
<template>
|
||||
<d2-container>
|
||||
<template slot="header">SVG图标组件</template>
|
||||
<el-row>
|
||||
<el-col class="icon-card" :span="4" v-for="(icon, index) in $IconSvg" :key="index">
|
||||
<d2-icon-svg class="icon" :name="icon"/>
|
||||
<div class="icon-title">
|
||||
<span>{{icon}}</span>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</d2-container>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.icon-card {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
height: 150px;
|
||||
&:hover {
|
||||
.icon {
|
||||
transform: scale(1.1);
|
||||
}
|
||||
.icon-title {
|
||||
color: $color-text-main;
|
||||
}
|
||||
}
|
||||
}
|
||||
.icon {
|
||||
height: 80px;
|
||||
width: 80px;
|
||||
transition: all .3s;
|
||||
cursor: pointer;
|
||||
}
|
||||
.icon-title {
|
||||
font-size: 12px;
|
||||
margin-top: 10px;
|
||||
color: $color-text-normal;
|
||||
}
|
||||
</style>
|
||||
@@ -1,22 +0,0 @@
|
||||
<template>
|
||||
<d2-container>
|
||||
<template slot="header">图标组件</template>
|
||||
<d2-icon class="d2-mr-10"/>
|
||||
<d2-icon name="github" class="d2-mr-10"/>
|
||||
<d2-icon name="github" style="font-size: 100px;" class="d2-mr-10"/>
|
||||
<d2-icon name="github" class="icon-demo"/>
|
||||
</d2-container>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.icon-demo {
|
||||
transition: all .3s;
|
||||
font-size: 100px;
|
||||
color: #409EFF;
|
||||
@extend %unable-select;
|
||||
&:hover{
|
||||
color: #F56C6C;
|
||||
transform: scale(1.2) rotate(30deg);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,46 +0,0 @@
|
||||
<template>
|
||||
<d2-container>
|
||||
<template slot="header">
|
||||
<el-radio-group v-model="showIndex" size="mini">
|
||||
<el-radio-button
|
||||
v-for="(item, index) in radioOptions"
|
||||
:key="index"
|
||||
:label="item.value">
|
||||
{{item.label}}
|
||||
</el-radio-button>
|
||||
</el-radio-group>
|
||||
</template>
|
||||
<el-row style="margin: -10px;">
|
||||
<el-alert title="点击图标复制代码" type="info" class="d2-m-10" style="width: auto;"/>
|
||||
<el-col v-for="(iconItem, iconIndex) in iconShow.icon" :key="iconIndex" :span="6" class="d2-p-10">
|
||||
<d2-icon-cell :icon="iconItem"/>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</d2-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import icon from './data/index'
|
||||
export default {
|
||||
components: {
|
||||
'd2-icon-cell': () => import('./components/d2-icon-cell')
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
icon,
|
||||
showIndex: 12
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
iconShow () {
|
||||
return this.icon[this.showIndex]
|
||||
},
|
||||
radioOptions () {
|
||||
return this.icon.map((e, index) => ({
|
||||
label: e.title,
|
||||
value: index
|
||||
}))
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,24 +0,0 @@
|
||||
<template>
|
||||
<d2-container>
|
||||
<template slot="header">svg 图标选择器</template>
|
||||
<div class="d2-mb">
|
||||
<p class="d2-mt-0 d2-mb-10">一般用法 | {{icon || '未选择'}}</p>
|
||||
<d2-icon-svg-select v-model="icon"/>
|
||||
</div>
|
||||
<div class="d2-mb">
|
||||
<p class="d2-mt-0 d2-mb-10">用户可以输入 | {{icon2 || '未选择'}}</p>
|
||||
<d2-icon-svg-select v-model="icon2" :user-input="true"/>
|
||||
</div>
|
||||
</d2-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
icon: '',
|
||||
icon2: ''
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,56 +0,0 @@
|
||||
<template>
|
||||
<d2-container>
|
||||
<template slot="header">图标选择器</template>
|
||||
<div class="title-group">
|
||||
<p class="title">一般用法</p>
|
||||
<p class="sub-title">
|
||||
<template v-if="icon">
|
||||
选择的图标 {{icon}}
|
||||
<i :class="'fa fa-' + icon"></i>
|
||||
</template>
|
||||
<template v-else>未选择</template>
|
||||
</p>
|
||||
</div>
|
||||
<d2-icon-select v-model="icon"/>
|
||||
<div class="title-group">
|
||||
<p class="title">用户可以输入</p>
|
||||
<p class="sub-title">
|
||||
<template v-if="icon2">
|
||||
选择的图标 {{icon2}}
|
||||
<i :class="'fa fa-' + icon2"></i>
|
||||
</template>
|
||||
<template v-else>未选择</template>
|
||||
</p>
|
||||
</div>
|
||||
<d2-icon-select v-model="icon2" :user-input="true"/>
|
||||
</d2-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
icon: '',
|
||||
icon2: ''
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.title-group {
|
||||
margin-top: 20px;
|
||||
margin-bottom: 10px;
|
||||
&:first-child {
|
||||
margin-top: 0px;
|
||||
}
|
||||
.title {
|
||||
margin: 0px;
|
||||
}
|
||||
.sub-title {
|
||||
margin: 0px;
|
||||
color: $color-text-sub;
|
||||
font-size: 10px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,21 +0,0 @@
|
||||
<template>
|
||||
<d2-container type="ghost">
|
||||
<d2-module-index-banner slot="header" v-bind="banner"/>
|
||||
<d2-module-index-menu :menu="menu"/>
|
||||
</d2-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import menu from '@/menu/modules/demo-components'
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
menu,
|
||||
banner: {
|
||||
title: 'COMPONENTS',
|
||||
subTitle: 'D2Admin 为你提供了一些上手即用的组件'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,24 +0,0 @@
|
||||
<template>
|
||||
<d2-container>
|
||||
<tree-view :data="packJson" :options="options"/>
|
||||
</d2-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Vue from 'vue'
|
||||
import vueJsonTreeView from 'vue-json-tree-view'
|
||||
import packJson from '../../../../../package.json'
|
||||
Vue.use(vueJsonTreeView)
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
options: {
|
||||
maxDepth: 10,
|
||||
rootObjectKey: 'package.json',
|
||||
modifiable: false
|
||||
},
|
||||
packJson
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,122 +0,0 @@
|
||||
<template>
|
||||
<d2-container type="full" class="page">
|
||||
<d2-grid-layout
|
||||
v-bind="layout"
|
||||
@layout-updated="layoutUpdatedHandler">
|
||||
<d2-grid-item
|
||||
v-for="(item, index) in layout.layout"
|
||||
:key="index"
|
||||
v-bind="item"
|
||||
@resize="resizeHandler"
|
||||
@move="moveHandler"
|
||||
@resized="resizedHandler"
|
||||
@moved="movedHandler">
|
||||
<el-card shadow="never" class="page_card">
|
||||
<el-tag size="mini" type="info" slot="header">Card {{item.i}}</el-tag>
|
||||
<template v-if="item.i === '0'">
|
||||
<div class="d2-mb">拖拽卡片调整位置</div>
|
||||
<div class="d2-mb">拖拽卡片右下角的手柄调整卡片大小</div>
|
||||
<div class="d2-mb">在控制台打印出数据变化</div>
|
||||
</template>
|
||||
</el-card>
|
||||
</d2-grid-item>
|
||||
</d2-grid-layout>
|
||||
</d2-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Vue from 'vue'
|
||||
import { GridLayout, GridItem } from 'vue-grid-layout'
|
||||
Vue.component('d2-grid-layout', GridLayout)
|
||||
Vue.component('d2-grid-item', GridItem)
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
layout: {
|
||||
layout: [
|
||||
{ x: 0, y: 0, w: 4, h: 10, i: '0' },
|
||||
{ x: 4, y: 0, w: 2, h: 5, i: '1' },
|
||||
{ x: 6, y: 0, w: 4, h: 5, i: '2' },
|
||||
{ x: 10, y: 0, w: 2, h: 10, i: '3' },
|
||||
{ x: 4, y: 5, w: 4, h: 5, i: '4' },
|
||||
{ x: 8, y: 5, w: 2, h: 5, i: '5' },
|
||||
{ x: 0, y: 10, w: 8, h: 5, i: '6' },
|
||||
{ x: 8, y: 10, w: 4, h: 5, i: '7' }
|
||||
],
|
||||
colNum: 12,
|
||||
rowHeight: 30,
|
||||
isDraggable: true,
|
||||
isResizable: true,
|
||||
isMirrored: false,
|
||||
verticalCompact: true,
|
||||
margin: [10, 10],
|
||||
useCssTransforms: true
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
// 加载完成后显示提示
|
||||
this.showInfo()
|
||||
},
|
||||
methods: {
|
||||
log (arg1 = 'log', ...logs) {
|
||||
if (logs.length === 0) {
|
||||
console.log(arg1)
|
||||
} else {
|
||||
console.group(arg1)
|
||||
logs.forEach(e => {
|
||||
console.log(e)
|
||||
})
|
||||
console.groupEnd()
|
||||
}
|
||||
},
|
||||
// 显示提示
|
||||
showInfo () {
|
||||
this.$notify({
|
||||
title: '提示',
|
||||
message: '你可以按住卡片拖拽改变位置;或者在每个卡片的右下角拖动,调整卡片大小'
|
||||
})
|
||||
},
|
||||
// 测试代码
|
||||
layoutUpdatedHandler (newLayout) {
|
||||
console.group('layoutUpdatedHandler')
|
||||
newLayout.forEach(e => {
|
||||
console.log(`{'x': ${e.x}, 'y': ${e.y}, 'w': ${e.w}, 'h': ${e.h}, 'i': '${e.i}'},`)
|
||||
})
|
||||
console.groupEnd()
|
||||
},
|
||||
resizeHandler (i, newH, newW) {
|
||||
this.log('resizeHandler', `i: ${i}, newH: ${newH}, newW: ${newW}`)
|
||||
},
|
||||
moveHandler (i, newX, newY) {
|
||||
this.log('moveHandler', `i: ${i}, newX: ${newX}, newY: ${newY}`)
|
||||
},
|
||||
resizedHandler (i, newH, newW, newHPx, newWPx) {
|
||||
this.log('resizedHandler', `i: ${i}, newH: ${newH}, newW: ${newW}, newHPx: ${newHPx}, newWPx: ${newWPx}`)
|
||||
},
|
||||
movedHandler (i, newX, newY) {
|
||||
this.log('movedHandler', `i: ${i}, newX: ${newX}, newY: ${newY}`)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.page {
|
||||
.vue-grid-layout {
|
||||
background-color: $color-bg;
|
||||
border-radius: 4px;
|
||||
margin: -10px;
|
||||
.page_card {
|
||||
height: 100%;
|
||||
@extend %unable-select;
|
||||
}
|
||||
.vue-resizable-handle {
|
||||
opacity: .3;
|
||||
&:hover{
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,37 +0,0 @@
|
||||
<template>
|
||||
<d2-container type="card">
|
||||
<template slot="header">区域划分</template>
|
||||
<div style="height: 400px; margin: -16px;">
|
||||
<SplitPane :min-percent='20' :default-percent='30' split="vertical">
|
||||
<template slot="paneL"><div style="margin: 10px;">左</div></template>
|
||||
<template slot="paneR">
|
||||
<SplitPane split="horizontal">
|
||||
<template slot="paneL"><div style="margin: 10px;">右上</div></template>
|
||||
<template slot="paneR"><div style="margin: 10px;">右下</div></template>
|
||||
</SplitPane>
|
||||
</template>
|
||||
</SplitPane>
|
||||
</div>
|
||||
</d2-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Vue from 'vue'
|
||||
import SplitPane from 'vue-splitpane'
|
||||
Vue.component('SplitPane', SplitPane)
|
||||
export default {
|
||||
mounted () {
|
||||
// 加载完成后显示提示
|
||||
this.showInfo()
|
||||
},
|
||||
methods: {
|
||||
// 显示提示
|
||||
showInfo () {
|
||||
this.$notify({
|
||||
title: '提示',
|
||||
message: '在横向或者纵向的分割线上拖拽调整分区大小'
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -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)
|
||||
})
|
||||
```
|
||||
|
||||
```
|
||||
<div>
|
||||
<p>Hello World</p>
|
||||
</div>
|
||||
```
|
||||
|
||||
```
|
||||
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)
|
||||
@@ -1,17 +0,0 @@
|
||||
<template>
|
||||
<d2-container>
|
||||
<template slot="header">指定资源</template>
|
||||
<d2-markdown :source="doc" highlight/>
|
||||
</d2-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import doc from './md/doc.md'
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
doc
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,6 +0,0 @@
|
||||
<template>
|
||||
<d2-container>
|
||||
<template slot="header">异步加载文件</template>
|
||||
<d2-markdown url="markdown/demo.md"/>
|
||||
</d2-container>
|
||||
</template>
|
||||
@@ -1,5 +0,0 @@
|
||||
<template>
|
||||
<d2-container type="card">
|
||||
<p>src/views/demo/playground/add-routes/alternates/1.vue</p>
|
||||
</d2-container>
|
||||
</template>
|
||||
@@ -1,5 +0,0 @@
|
||||
<template>
|
||||
<d2-container type="card">
|
||||
<p>src/views/demo/playground/add-routes/alternates/2.vue</p>
|
||||
</d2-container>
|
||||
</template>
|
||||
@@ -1,5 +0,0 @@
|
||||
<template>
|
||||
<d2-container type="card">
|
||||
<p>src/views/demo/playground/add-routes/alternates/3.vue</p>
|
||||
</d2-container>
|
||||
</template>
|
||||
@@ -1,109 +0,0 @@
|
||||
<template>
|
||||
<d2-container>
|
||||
<el-alert
|
||||
title="由于演示功能特殊,请注意在需要时刷新您的浏览器(以重置路由设置)查看效果"
|
||||
type="warning"
|
||||
show-icon/>
|
||||
<d2-highlight :code="dataView"/>
|
||||
<el-form label-position="top">
|
||||
<el-form-item label="创建路由(你可以假设上面是接口数据)">
|
||||
<el-button-group>
|
||||
<el-button
|
||||
v-for="item in setting"
|
||||
:key="item.component"
|
||||
@click="onClick(item)">
|
||||
{{item.title}}
|
||||
</el-button>
|
||||
</el-button-group>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</d2-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { cloneDeep } from 'lodash'
|
||||
import { mapState, mapMutations } from 'vuex'
|
||||
import { frameInRoutes } from '@/router/routes'
|
||||
import layoutHeaderAside from '@/layout/header-aside'
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
title: '',
|
||||
setting: [
|
||||
{ title: '追加页面 1', name: 'add-routes-1', path: 'add-routes/1', component: '1' },
|
||||
{ title: '追加页面 2', name: 'add-routes-2', path: 'add-routes/2', component: '2' },
|
||||
{ title: '追加页面 3', name: 'add-routes-3', path: 'add-routes/3', component: '3' }
|
||||
]
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState('d2admin/menu', [
|
||||
'header'
|
||||
]),
|
||||
dataView () {
|
||||
return JSON.stringify(this.setting, null, 2)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
...mapMutations({
|
||||
pageInit: 'd2admin/page/init',
|
||||
headerSet: 'd2admin/menu/headerSet'
|
||||
}),
|
||||
onClick ({ title, name, path, component }) {
|
||||
// vue router 的设计暂时不能支持在路由示例上访问动态添加的路由
|
||||
// 目前可行的解决方法是自行维护一个存储路由数据的位置
|
||||
// https://github.com/vuejs/vue-router/issues/1234
|
||||
// https://github.com/vuejs/vue-router/issues/1859
|
||||
// https://github.com/vuejs/vue-router/issues/1955
|
||||
// https://github.com/vuejs/vue-router/issues/2454
|
||||
// https://github.com/vuejs/vue-router/issues/2280
|
||||
// 所以暂时先不做对路由已经存在的判断
|
||||
const route = [
|
||||
{
|
||||
path: '/demo/playground',
|
||||
component: layoutHeaderAside,
|
||||
children: [
|
||||
{
|
||||
path,
|
||||
name,
|
||||
component: () => import('@/views/demo/playground/add-routes/alternates/' + component + '.vue'),
|
||||
meta: {
|
||||
title
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
this.$router.addRoutes(route)
|
||||
// 更新标签页池
|
||||
this.pageInit([
|
||||
...frameInRoutes,
|
||||
...route
|
||||
])
|
||||
// 演示更新菜单
|
||||
const menuGroup = {
|
||||
title: '临时菜单',
|
||||
icon: 'plus-square',
|
||||
children: []
|
||||
}
|
||||
const menu = {
|
||||
path: `/demo/playground/${path}`,
|
||||
title,
|
||||
icon: 'file-o'
|
||||
}
|
||||
const header = cloneDeep(this.header)
|
||||
const menuGroupIndex = header.findIndex(e => e.title === menuGroup.title)
|
||||
// 如果顶栏菜单已经有这个组,就在组里添加项目,反之新建一个菜单组
|
||||
if (menuGroupIndex >= 0) {
|
||||
header[menuGroupIndex].children.push(menu)
|
||||
} else {
|
||||
menuGroup.children.push(menu)
|
||||
header.push(menuGroup)
|
||||
}
|
||||
this.headerSet(header)
|
||||
// 跳转
|
||||
this.$router.push({ name })
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,33 +0,0 @@
|
||||
<template>
|
||||
<d2-container>
|
||||
<template slot="header">
|
||||
<el-alert
|
||||
type="success"
|
||||
:closable="false"
|
||||
title="这个页面展示的是全部数据的存储结构,包括系统区域和存储区域,涵盖所有用户,也就是整个 D2Admin 的数据存储结构"/>
|
||||
</template>
|
||||
<d2-highlight :code="dbData"/>
|
||||
<el-button slot="footer" type="primary" @click="load">
|
||||
重新获取本地数据
|
||||
</el-button>
|
||||
</d2-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import util from '@/libs/util'
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
dbData: ''
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.load()
|
||||
},
|
||||
methods: {
|
||||
load () {
|
||||
this.dbData = JSON.stringify(util.db.value(), null, 2)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,127 +0,0 @@
|
||||
<template>
|
||||
<d2-container>
|
||||
<template slot="header">
|
||||
<el-alert
|
||||
type="success"
|
||||
:closable="false"
|
||||
title="路由存储指当前路由的存储区域,
|
||||
不同路由之间存储不会相互干扰,
|
||||
使用 await this.$store.dispatch('d2admin/db/databasePage') 获得存储实例进行操作,
|
||||
不同路由条件下获取的存储实例指向位置不同,
|
||||
可以指定路由区分依据 name | path | fullPath,
|
||||
默认根据路由的 name 区分不同的路由"/>
|
||||
</template>
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<p class="d2-mt-0">增加不重复字段</p>
|
||||
<el-button @click="handleSetRandom">增加</el-button>
|
||||
<p>增加自定义字段</p>
|
||||
<el-input v-model="keyNameToSet" placeholder="字段名" class="d2-mr-5" style="width: 100px;"/>
|
||||
<el-input v-model="valueToSet" placeholder="值" class="d2-mr-5" style="width: 100px;"/>
|
||||
<el-button @click="handleSet">增加</el-button>
|
||||
<p>删除字段</p>
|
||||
<el-select
|
||||
v-model="keyNameToDelete"
|
||||
placeholder="请选择要删除的 key">
|
||||
<el-option
|
||||
v-for="item in keyNameList"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value">
|
||||
</el-option>
|
||||
</el-select>
|
||||
<p>清空当前用户数据</p>
|
||||
<el-button @click="handleClear">清空</el-button>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<d2-highlight :code="dataDisplay"/>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</d2-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { uniqueId } from 'lodash'
|
||||
import { mapActions } from 'vuex'
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
dataDisplay: '',
|
||||
keyNameToSet: '',
|
||||
valueToSet: '',
|
||||
keyNameList: [],
|
||||
keyNameToDelete: ''
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
keyNameToDelete (value) {
|
||||
if (value) {
|
||||
this.handleDelete(value)
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.load()
|
||||
},
|
||||
methods: {
|
||||
...mapActions('d2admin/db', [
|
||||
'databasePage',
|
||||
'databasePageClear'
|
||||
]),
|
||||
/**
|
||||
* 加载本地数据
|
||||
*/
|
||||
async load () {
|
||||
const db = await this.databasePage()
|
||||
this.dataDisplay = JSON.stringify(db.value(), null, 2)
|
||||
this.keyNameList = Object.keys(db.value()).map(k => ({
|
||||
value: k,
|
||||
label: k
|
||||
}))
|
||||
},
|
||||
/**
|
||||
* 删除一个字段
|
||||
*/
|
||||
async handleDelete (name) {
|
||||
const db = await this.databasePage()
|
||||
db
|
||||
.unset(name)
|
||||
.write()
|
||||
this.load()
|
||||
this.keyNameToDelete = ''
|
||||
},
|
||||
/**
|
||||
* 清空当前用户的数据
|
||||
*/
|
||||
async handleClear () {
|
||||
await this.databasePageClear()
|
||||
this.load()
|
||||
},
|
||||
/**
|
||||
* 添加一个数据
|
||||
*/
|
||||
async handleSet () {
|
||||
if (this.keyNameToSet === '') {
|
||||
this.$message.error('字段名不能为空')
|
||||
return
|
||||
}
|
||||
const db = await this.databasePage()
|
||||
db
|
||||
.set(this.keyNameToSet, this.valueToSet)
|
||||
.write()
|
||||
this.load()
|
||||
},
|
||||
/**
|
||||
* 添加一个随机数据
|
||||
*/
|
||||
async handleSetRandom () {
|
||||
const id = uniqueId()
|
||||
const db = await this.databasePage()
|
||||
db
|
||||
.set(`uniqueKey${id}`, `value${id}`)
|
||||
.write()
|
||||
this.load()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,114 +0,0 @@
|
||||
<template>
|
||||
<d2-container>
|
||||
<template slot="header">
|
||||
<el-alert
|
||||
type="success"
|
||||
:closable="false"
|
||||
title="路由快照相当于路由存储一种快捷操作,
|
||||
会将传入的 vue instance 携带的 $data 全部持久化,
|
||||
下面的表单来自 Element 的表单示例,
|
||||
在 D2Admin 的本页示例中你可以随意填写这个表单,
|
||||
表单内容会自动实时持久化,
|
||||
无论是切换标签页、重新打开标签页、刷新浏览器、重开浏览器、重开浏览器标签页等,
|
||||
该页面数据都会自动恢复到上次填写的状态,
|
||||
这些都只需要你使用 D2Admin 提供的两个方法,
|
||||
总共只需要多写十几行代码"/>
|
||||
</template>
|
||||
<el-form ref="form" :model="form" label-width="80px" style="max-width: 600px; margin: 0px auto;">
|
||||
<el-form-item label="活动名称">
|
||||
<el-input v-model="form.name"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="活动区域">
|
||||
<el-select v-model="form.region" placeholder="请选择活动区域">
|
||||
<el-option label="区域一" value="shanghai"></el-option>
|
||||
<el-option label="区域二" value="beijing"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="活动时间">
|
||||
<el-col :span="11">
|
||||
<el-date-picker type="date" placeholder="选择日期" v-model="form.date1" style="width: 100%;"></el-date-picker>
|
||||
</el-col>
|
||||
<el-col :span="2" style="text-align: center;">-</el-col>
|
||||
<el-col :span="11">
|
||||
<el-time-picker type="fixed-time" placeholder="选择时间" v-model="form.date2" style="width: 100%;"></el-time-picker>
|
||||
</el-col>
|
||||
</el-form-item>
|
||||
<el-form-item label="即时配送">
|
||||
<el-switch v-model="form.delivery"></el-switch>
|
||||
</el-form-item>
|
||||
<el-form-item label="活动性质">
|
||||
<el-checkbox-group v-model="form.type">
|
||||
<el-checkbox label="线上活动" name="type"></el-checkbox>
|
||||
<el-checkbox label="地推活动" name="type"></el-checkbox>
|
||||
<el-checkbox label="线下活动" name="type"></el-checkbox>
|
||||
<el-checkbox label="品牌曝光" name="type"></el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="特殊资源">
|
||||
<el-radio-group v-model="form.resource">
|
||||
<el-radio label="线上品牌商赞助"></el-radio>
|
||||
<el-radio label="线下场地免费"></el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="活动形式">
|
||||
<el-input type="textarea" v-model="form.desc"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary">立即创建</el-button>
|
||||
<el-button>取消</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-button
|
||||
slot="footer"
|
||||
type="danger"
|
||||
@click="handleClear">
|
||||
<d2-icon name="trash-o"/>
|
||||
删除当前页面快照
|
||||
</el-button>
|
||||
</d2-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapActions } from 'vuex'
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
form: {
|
||||
name: '',
|
||||
region: '',
|
||||
date1: '',
|
||||
date2: '',
|
||||
delivery: false,
|
||||
type: [],
|
||||
resource: '',
|
||||
desc: ''
|
||||
}
|
||||
}
|
||||
},
|
||||
async created () {
|
||||
const data = await this.pageGet({ instance: this })
|
||||
for (const key in data) {
|
||||
this[key] = data[key]
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
$data: {
|
||||
handler () {
|
||||
this.pageSet({ instance: this })
|
||||
},
|
||||
deep: true
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
...mapActions('d2admin/db', [
|
||||
'pageSet',
|
||||
'pageGet',
|
||||
'pageClear'
|
||||
]),
|
||||
async handleClear () {
|
||||
await this.pageClear({ instance: this })
|
||||
this.$message.success('此页面快照已经删除,请重新进入该页面或者关闭选项卡重新打开')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,114 +0,0 @@
|
||||
<template>
|
||||
<d2-container>
|
||||
<template slot="header">
|
||||
<el-alert
|
||||
type="success"
|
||||
:closable="false"
|
||||
title="私有路由快照相当于私有路由存储一种快捷操作,
|
||||
会将传入的 vue instance 携带的 $data 全部根据用户区分持久化,
|
||||
下面的表单来自 Element 的表单示例,
|
||||
在 D2Admin 的本页示例中你可以随意填写这个表单,
|
||||
表单内容会自动实时持久化,
|
||||
无论是切换标签页、重新打开标签页、刷新浏览器、重开浏览器、重开浏览器标签页等,
|
||||
该页面数据都会自动恢复到上次填写的状态,
|
||||
这些都只需要你使用 D2Admin 提供的两个方法,
|
||||
总共只需要多写十几行代码"/>
|
||||
</template>
|
||||
<el-form ref="form" :model="form" label-width="80px" style="max-width: 600px; margin: 0px auto;">
|
||||
<el-form-item label="活动名称">
|
||||
<el-input v-model="form.name"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="活动区域">
|
||||
<el-select v-model="form.region" placeholder="请选择活动区域">
|
||||
<el-option label="区域一" value="shanghai"></el-option>
|
||||
<el-option label="区域二" value="beijing"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="活动时间">
|
||||
<el-col :span="11">
|
||||
<el-date-picker type="date" placeholder="选择日期" v-model="form.date1" style="width: 100%;"></el-date-picker>
|
||||
</el-col>
|
||||
<el-col :span="2" style="text-align: center;">-</el-col>
|
||||
<el-col :span="11">
|
||||
<el-time-picker type="fixed-time" placeholder="选择时间" v-model="form.date2" style="width: 100%;"></el-time-picker>
|
||||
</el-col>
|
||||
</el-form-item>
|
||||
<el-form-item label="即时配送">
|
||||
<el-switch v-model="form.delivery"></el-switch>
|
||||
</el-form-item>
|
||||
<el-form-item label="活动性质">
|
||||
<el-checkbox-group v-model="form.type">
|
||||
<el-checkbox label="线上活动" name="type"></el-checkbox>
|
||||
<el-checkbox label="地推活动" name="type"></el-checkbox>
|
||||
<el-checkbox label="线下活动" name="type"></el-checkbox>
|
||||
<el-checkbox label="品牌曝光" name="type"></el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="特殊资源">
|
||||
<el-radio-group v-model="form.resource">
|
||||
<el-radio label="线上品牌商赞助"></el-radio>
|
||||
<el-radio label="线下场地免费"></el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="活动形式">
|
||||
<el-input type="textarea" v-model="form.desc"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary">立即创建</el-button>
|
||||
<el-button>取消</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-button
|
||||
slot="footer"
|
||||
type="danger"
|
||||
@click="handleClear">
|
||||
<d2-icon name="trash-o"/>
|
||||
删除当前页面快照
|
||||
</el-button>
|
||||
</d2-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapActions } from 'vuex'
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
form: {
|
||||
name: '',
|
||||
region: '',
|
||||
date1: '',
|
||||
date2: '',
|
||||
delivery: false,
|
||||
type: [],
|
||||
resource: '',
|
||||
desc: ''
|
||||
}
|
||||
}
|
||||
},
|
||||
async created () {
|
||||
const data = await this.pageGet({ instance: this, user: true })
|
||||
for (const key in data) {
|
||||
this[key] = data[key]
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
$data: {
|
||||
handler () {
|
||||
this.pageSet({ instance: this, user: true })
|
||||
},
|
||||
deep: true
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
...mapActions('d2admin/db', [
|
||||
'pageSet',
|
||||
'pageGet',
|
||||
'pageClear'
|
||||
]),
|
||||
async handleClear () {
|
||||
await this.pageClear({ instance: this, user: true })
|
||||
this.$message.success('此页面快照已经删除,请重新进入该页面或者关闭选项卡重新打开')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,139 +0,0 @@
|
||||
<template>
|
||||
<d2-container>
|
||||
<template slot="header">
|
||||
<el-alert
|
||||
type="success"
|
||||
:closable="false"
|
||||
title="私有路由存储指当前路由的存储区域,
|
||||
并且同时还根据用户区分,
|
||||
相当于结合了 “路由存储” 和 “私有存储”,
|
||||
不同路由以及不同用户之间存储不会相互干扰,
|
||||
使用 await this.$store.dispatch('d2admin/db/databasePage', { user: true }) 获得存储实例进行操作,
|
||||
不同路由和用户条件下获取的存储实例指向位置不同,
|
||||
可以指定路由区分依据 name | path | fullPath,
|
||||
默认根据路由的 name 区分不同的路由"/>
|
||||
</template>
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<p class="d2-mt-0">增加不重复字段</p>
|
||||
<el-button @click="handleSetRandom">增加</el-button>
|
||||
<p>增加自定义字段</p>
|
||||
<el-input v-model="keyNameToSet" placeholder="字段名" class="d2-mr-5" style="width: 100px;"/>
|
||||
<el-input v-model="valueToSet" placeholder="值" class="d2-mr-5" style="width: 100px;"/>
|
||||
<el-button @click="handleSet">增加</el-button>
|
||||
<p>删除字段</p>
|
||||
<el-select
|
||||
v-model="keyNameToDelete"
|
||||
placeholder="请选择要删除的 key">
|
||||
<el-option
|
||||
v-for="item in keyNameList"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value">
|
||||
</el-option>
|
||||
</el-select>
|
||||
<p>清空当前用户数据</p>
|
||||
<el-button @click="handleClear">清空</el-button>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<d2-highlight :code="dataDisplay"/>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</d2-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { uniqueId } from 'lodash'
|
||||
import { mapActions } from 'vuex'
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
dataDisplay: '',
|
||||
keyNameToSet: '',
|
||||
valueToSet: '',
|
||||
keyNameList: [],
|
||||
keyNameToDelete: ''
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
keyNameToDelete (value) {
|
||||
if (value) {
|
||||
this.handleDelete(value)
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.load()
|
||||
},
|
||||
methods: {
|
||||
...mapActions('d2admin/db', [
|
||||
'databasePage',
|
||||
'databasePageClear'
|
||||
]),
|
||||
/**
|
||||
* 加载本地数据
|
||||
*/
|
||||
async load () {
|
||||
const db = await this.databasePage({
|
||||
user: true
|
||||
})
|
||||
this.dataDisplay = JSON.stringify(db.value(), null, 2)
|
||||
this.keyNameList = Object.keys(db.value()).map(k => ({
|
||||
value: k,
|
||||
label: k
|
||||
}))
|
||||
},
|
||||
/**
|
||||
* 删除一个字段
|
||||
*/
|
||||
async handleDelete (name) {
|
||||
const db = await this.databasePage({
|
||||
user: true
|
||||
})
|
||||
db
|
||||
.unset(name)
|
||||
.write()
|
||||
this.load()
|
||||
this.keyNameToDelete = ''
|
||||
},
|
||||
/**
|
||||
* 清空当前用户的数据
|
||||
*/
|
||||
async handleClear () {
|
||||
await this.databasePageClear({
|
||||
user: true
|
||||
})
|
||||
this.load()
|
||||
},
|
||||
/**
|
||||
* 添加一个数据
|
||||
*/
|
||||
async handleSet () {
|
||||
if (this.keyNameToSet === '') {
|
||||
this.$message.error('字段名不能为空')
|
||||
return
|
||||
}
|
||||
const db = await this.databasePage({
|
||||
user: true
|
||||
})
|
||||
db
|
||||
.set(this.keyNameToSet, this.valueToSet)
|
||||
.write()
|
||||
this.load()
|
||||
},
|
||||
/**
|
||||
* 添加一个随机数据
|
||||
*/
|
||||
async handleSetRandom () {
|
||||
const id = uniqueId()
|
||||
const db = await this.databasePage({
|
||||
user: true
|
||||
})
|
||||
db
|
||||
.set(`uniqueKey${id}`, `value${id}`)
|
||||
.write()
|
||||
this.load()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,123 +0,0 @@
|
||||
<template>
|
||||
<d2-container>
|
||||
<template slot="header">
|
||||
<el-alert
|
||||
type="success"
|
||||
:closable="false"
|
||||
title="公用存储指所有用户共用的存储区域,
|
||||
使用 await this.$store.dispatch('d2admin/db/database') 获得存储实例进行操作"/>
|
||||
</template>
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<p class="d2-mt-0">增加不重复字段</p>
|
||||
<el-button @click="handleSetRandom">增加</el-button>
|
||||
<p>增加自定义字段</p>
|
||||
<el-input v-model="keyNameToSet" placeholder="字段名" class="d2-mr-5" style="width: 100px;"/>
|
||||
<el-input v-model="valueToSet" placeholder="值" class="d2-mr-5" style="width: 100px;"/>
|
||||
<el-button @click="handleSet">增加</el-button>
|
||||
<p>删除字段</p>
|
||||
<el-select
|
||||
v-model="keyNameToDelete"
|
||||
placeholder="请选择要删除的 key">
|
||||
<el-option
|
||||
v-for="item in keyNameList"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value">
|
||||
</el-option>
|
||||
</el-select>
|
||||
<p>清空当前用户数据</p>
|
||||
<el-button @click="handleClear">清空</el-button>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<d2-highlight :code="dataDisplay"/>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</d2-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { uniqueId } from 'lodash'
|
||||
import { mapActions } from 'vuex'
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
dataDisplay: '',
|
||||
keyNameToSet: '',
|
||||
valueToSet: '',
|
||||
keyNameList: [],
|
||||
keyNameToDelete: ''
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
keyNameToDelete (value) {
|
||||
if (value) {
|
||||
this.handleDelete(value)
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.load()
|
||||
},
|
||||
methods: {
|
||||
...mapActions('d2admin/db', [
|
||||
'database',
|
||||
'databaseClear'
|
||||
]),
|
||||
/**
|
||||
* 加载本地数据
|
||||
*/
|
||||
async load () {
|
||||
const db = await this.database()
|
||||
this.dataDisplay = JSON.stringify(db.value(), null, 2)
|
||||
this.keyNameList = Object.keys(db.value()).map(k => ({
|
||||
value: k,
|
||||
label: k
|
||||
}))
|
||||
},
|
||||
/**
|
||||
* 删除一个字段
|
||||
*/
|
||||
async handleDelete (name) {
|
||||
const db = await this.database()
|
||||
db
|
||||
.unset(name)
|
||||
.write()
|
||||
this.load()
|
||||
this.keyNameToDelete = ''
|
||||
},
|
||||
/**
|
||||
* 清空当前用户的数据
|
||||
*/
|
||||
async handleClear () {
|
||||
await this.databaseClear()
|
||||
this.load()
|
||||
},
|
||||
/**
|
||||
* 添加一个数据
|
||||
*/
|
||||
async handleSet () {
|
||||
if (this.keyNameToSet === '') {
|
||||
this.$message.error('字段名不能为空')
|
||||
return
|
||||
}
|
||||
const db = await this.database()
|
||||
db
|
||||
.set(this.keyNameToSet, this.valueToSet)
|
||||
.write()
|
||||
this.load()
|
||||
},
|
||||
/**
|
||||
* 添加一个随机数据
|
||||
*/
|
||||
async handleSetRandom () {
|
||||
const id = uniqueId()
|
||||
const db = await this.database()
|
||||
db
|
||||
.set(`uniqueKey${id}`, `value${id}`)
|
||||
.write()
|
||||
this.load()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,125 +0,0 @@
|
||||
<template>
|
||||
<d2-container>
|
||||
<template slot="header">
|
||||
<el-alert
|
||||
type="success"
|
||||
:closable="false"
|
||||
title="私有存储指当前用户专用的存储区域,
|
||||
不同用户之间存储不会相互干扰,
|
||||
使用 await this.$store.dispatch('d2admin/db/database', { user: true }) 获得存储实例进行操作,
|
||||
不同用户条件下获取的存储实例指向位置不同"/>
|
||||
</template>
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<p class="d2-mt-0">增加不重复字段</p>
|
||||
<el-button @click="handleSetRandom">增加</el-button>
|
||||
<p>增加自定义字段</p>
|
||||
<el-input v-model="keyNameToSet" placeholder="字段名" class="d2-mr-5" style="width: 100px;"/>
|
||||
<el-input v-model="valueToSet" placeholder="值" class="d2-mr-5" style="width: 100px;"/>
|
||||
<el-button @click="handleSet">增加</el-button>
|
||||
<p>删除字段</p>
|
||||
<el-select
|
||||
v-model="keyNameToDelete"
|
||||
placeholder="请选择要删除的 key">
|
||||
<el-option
|
||||
v-for="item in keyNameList"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value">
|
||||
</el-option>
|
||||
</el-select>
|
||||
<p>清空当前用户数据</p>
|
||||
<el-button @click="handleClear">清空</el-button>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<d2-highlight :code="dataDisplay"/>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</d2-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { uniqueId } from 'lodash'
|
||||
import { mapActions } from 'vuex'
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
dataDisplay: '',
|
||||
keyNameToSet: '',
|
||||
valueToSet: '',
|
||||
keyNameList: [],
|
||||
keyNameToDelete: ''
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
keyNameToDelete (value) {
|
||||
if (value) {
|
||||
this.handleDelete(value)
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.load()
|
||||
},
|
||||
methods: {
|
||||
...mapActions('d2admin/db', [
|
||||
'database',
|
||||
'databaseClear'
|
||||
]),
|
||||
/**
|
||||
* 加载本地数据
|
||||
*/
|
||||
async load () {
|
||||
const db = await this.database({ user: true })
|
||||
this.dataDisplay = JSON.stringify(db.value(), null, 2)
|
||||
this.keyNameList = Object.keys(db.value()).map(k => ({
|
||||
value: k,
|
||||
label: k
|
||||
}))
|
||||
},
|
||||
/**
|
||||
* 删除一个字段
|
||||
*/
|
||||
async handleDelete (name) {
|
||||
const db = await this.database({ user: true })
|
||||
db
|
||||
.unset(name)
|
||||
.write()
|
||||
this.load()
|
||||
this.keyNameToDelete = ''
|
||||
},
|
||||
/**
|
||||
* 清空当前用户的数据
|
||||
*/
|
||||
async handleClear () {
|
||||
await this.databaseClear({ user: true })
|
||||
this.load()
|
||||
},
|
||||
/**
|
||||
* 添加一个数据
|
||||
*/
|
||||
async handleSet () {
|
||||
if (this.keyNameToSet === '') {
|
||||
this.$message.error('字段名不能为空')
|
||||
return
|
||||
}
|
||||
const db = await this.database({ user: true })
|
||||
db
|
||||
.set(this.keyNameToSet, this.valueToSet)
|
||||
.write()
|
||||
this.load()
|
||||
},
|
||||
/**
|
||||
* 添加一个随机数据
|
||||
*/
|
||||
async handleSetRandom () {
|
||||
const id = uniqueId()
|
||||
const db = await this.database({ user: true })
|
||||
db
|
||||
.set(`uniqueKey${id}`, `value${id}`)
|
||||
.write()
|
||||
this.load()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
16
src/views/demo/playground/env/index.vue
vendored
16
src/views/demo/playground/env/index.vue
vendored
@@ -1,16 +0,0 @@
|
||||
<template>
|
||||
<d2-container type="card">
|
||||
<template slot="header">process.env</template>
|
||||
<d2-highlight :code="env"/>
|
||||
</d2-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
env: JSON.stringify(process.env, null, 2)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,3 +0,0 @@
|
||||
<template>
|
||||
<d2-container-frame src="https://d2.pub/doc/d2-admin"/>
|
||||
</template>
|
||||
@@ -1,3 +0,0 @@
|
||||
<template>
|
||||
<d2-container-frame :src="`${$baseUrl}html/demo.html`"/>
|
||||
</template>
|
||||
@@ -1,3 +0,0 @@
|
||||
<template>
|
||||
<d2-container-frame :src="`${$baseUrl}report.html`"/>
|
||||
</template>
|
||||
@@ -1,21 +0,0 @@
|
||||
<template>
|
||||
<d2-container type="ghost">
|
||||
<d2-module-index-banner slot="header" v-bind="banner"/>
|
||||
<d2-module-index-menu :menu="menu"/>
|
||||
</d2-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import menu from '@/menu/modules/demo-playground'
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
menu,
|
||||
banner: {
|
||||
title: 'PLAYGROUND',
|
||||
subTitle: '在这里可以测试一些 D2Admin 的系统功能'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,22 +0,0 @@
|
||||
<template>
|
||||
<d2-container>
|
||||
<p class="d2-mt-0">
|
||||
<el-radio-group v-model="$i18n.locale">
|
||||
<el-radio-button
|
||||
v-for="language in $languages"
|
||||
:key="language.value"
|
||||
:label="language.value">
|
||||
{{ language.label }}
|
||||
</el-radio-button>
|
||||
</el-radio-group>
|
||||
</p>
|
||||
<el-alert
|
||||
:title="$t('page.demo.playground.locales.text')"
|
||||
type="success">
|
||||
</el-alert>
|
||||
<d2-link-btn
|
||||
slot="footer"
|
||||
title="文档"
|
||||
link="https://d2.pub/doc/d2-admin/locales"/>
|
||||
</d2-container>
|
||||
</template>
|
||||
@@ -1,20 +0,0 @@
|
||||
<template>
|
||||
<d2-container>
|
||||
<template slot="header">Ajax 错误</template>
|
||||
<p class="d2-mt-0">请打开浏览器控制台,然后点击下面的按钮,尝试访问一个不存在的网络地址</p>
|
||||
<el-button type="danger" @click="handleClick">请求错误的地址</el-button>
|
||||
<p>此错误已经被记录在日志页面,并在页面右上"日志按钮"区域显示提示信息</p>
|
||||
</d2-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { DEMO_LOG_AJAX } from '@/api/demo.js'
|
||||
|
||||
export default {
|
||||
methods: {
|
||||
handleClick () {
|
||||
DEMO_LOG_AJAX()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 65 KiB |
@@ -1,67 +0,0 @@
|
||||
<template>
|
||||
<d2-container class="page">
|
||||
<p class="d2-mt-0">$log.capsule</p>
|
||||
<el-button size="small" type="primary" @click="$log.capsule('title', 'primary')">
|
||||
$log.capsule('title', 'primary')
|
||||
</el-button>
|
||||
<el-button size="small" type="success" @click="$log.capsule('title', 'success', 'success')">
|
||||
$log.capsule('title', 'success', 'success')
|
||||
</el-button>
|
||||
<el-button size="small" type="warning" @click="$log.capsule('title', 'warning', 'warning')">
|
||||
$log.capsule('title', 'warning', 'warning')
|
||||
</el-button>
|
||||
<el-button size="small" type="danger" @click="$log.capsule('title', 'danger', 'danger')">
|
||||
$log.capsule('title', 'danger', 'danger')
|
||||
</el-button>
|
||||
<p>$log.colorful</p>
|
||||
<el-button size="small" @click="handleColorful">
|
||||
colorful
|
||||
</el-button>
|
||||
<p>$log.default | primary | success | warning | danger</p>
|
||||
<el-button size="small" @click="$log.default('default style')">
|
||||
$log.default('default style')
|
||||
</el-button>
|
||||
<el-button size="small" type="primary" @click="$log.primary('primary style')">
|
||||
$log.primary('primary style')
|
||||
</el-button>
|
||||
<el-button size="small" type="success" @click="$log.success('success style')">
|
||||
$log.success('success style')
|
||||
</el-button>
|
||||
<el-button size="small" type="warning" @click="$log.warning('warning style')">
|
||||
$log.warning('warning style')
|
||||
</el-button>
|
||||
<el-button size="small" type="danger" @click="$log.danger('danger style')">
|
||||
$log.danger('danger style')
|
||||
</el-button>
|
||||
<p>效果 ( Chrome )</p>
|
||||
<img
|
||||
class="page__image-demo"
|
||||
src="./image/demo.png">
|
||||
</d2-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
methods: {
|
||||
handleColorful () {
|
||||
this.$log.colorful([
|
||||
{ text: 'H', type: 'default' },
|
||||
{ text: 'e', type: 'primary' },
|
||||
{ text: 'l', type: 'success' },
|
||||
{ text: 'l', type: 'warning' },
|
||||
{ text: 'o', type: 'danger' }
|
||||
])
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.page {
|
||||
.page__image-demo {
|
||||
border-radius: 4px;
|
||||
width: 260px;
|
||||
border: 1px solid $color-border-1;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,18 +0,0 @@
|
||||
<template>
|
||||
<d2-container>
|
||||
<template slot="header">捕获错误信息</template>
|
||||
<p class="d2-mt-0">请打开浏览器控制台,然后点击下面的按钮</p>
|
||||
<el-button type="danger" @click="handleNewError">触发一个错误</el-button>
|
||||
<p>此错误已经被记录在日志页面,并在页面右上"日志按钮"区域显示提示信息</p>
|
||||
</d2-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
methods: {
|
||||
handleNewError () {
|
||||
console.log(a) // eslint-disable-line
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,28 +0,0 @@
|
||||
<template>
|
||||
<d2-container>
|
||||
<template slot="header">记录日志内容</template>
|
||||
<p class="d2-mt-0">在下方输入你要记录的日志,然后点击记录按钮</p>
|
||||
<el-input
|
||||
v-model="text"
|
||||
placeholder="日志内容"
|
||||
class="d2-mr-10"
|
||||
style="width: 200px;"/>
|
||||
<el-button type="primary" @click="handleAdd">记录</el-button>
|
||||
<p>此信息已经被记录在日志页面,并在页面右上"日志按钮"区域显示提示信息</p>
|
||||
</d2-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
text: 'some text'
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleAdd () {
|
||||
this.$log.push(this.text)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,16 +0,0 @@
|
||||
<template>
|
||||
<d2-container type="card">
|
||||
<h2 class="d2-mt-0">$route.params.username: {{$route.params.username}}</h2>
|
||||
<h2>$route.query.userid: {{$route.query.userid}}</h2>
|
||||
<p>你可以尝试返回发送数据页面修改数据重新发送,或者切换到其它页面后刷新浏览器再返回本业观察参数保留</p>
|
||||
<el-button type="primary" @click="$router.push({ name: 'demo-playground-page-argu-send' })">返回发送数据的页面</el-button>
|
||||
</d2-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
mounted () {
|
||||
console.log('this.$route', this.$route)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,55 +0,0 @@
|
||||
<template>
|
||||
<d2-container type="card">
|
||||
<el-form :model="sendForm" :rules="rules" label-position="top" ref="sendForm">
|
||||
<el-form-item label="username 通过动态路由匹配发送" prop="username">
|
||||
<el-input v-model="sendForm.username" style="width: 300px;"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="userid 通过参数发送" prop="userid">
|
||||
<el-input v-model="sendForm.userid" style="width: 300px;"/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="handleSubmit('sendForm')">跳转到接收页面</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</d2-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
sendForm: {
|
||||
username: 'FairyEver',
|
||||
userid: '001'
|
||||
},
|
||||
rules: {
|
||||
username: [
|
||||
{ required: true, message: '请输入要发送的用户名', trigger: 'blur' }
|
||||
],
|
||||
userid: [
|
||||
{ required: true, message: '请输入要发送的用户ID', trigger: 'blur' }
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleSubmit (formName) {
|
||||
this.$refs[formName].validate(valid => {
|
||||
if (valid) {
|
||||
this.$router.push({
|
||||
name: 'demo-playground-page-argu-get',
|
||||
params: {
|
||||
username: this.sendForm.username
|
||||
},
|
||||
query: {
|
||||
userid: this.sendForm.userid
|
||||
}
|
||||
})
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,17 +0,0 @@
|
||||
<template>
|
||||
<d2-container type="card">
|
||||
<template slot="header">这个页面不会被 keep-alive</template>
|
||||
<p class="d2-mt-0">在下面的输入框输入任意字符后,切换到其它页面,再回到此页时输入框文字消失,证明没有被缓存</p>
|
||||
<el-input v-model="value" placeholder="input here"></el-input>
|
||||
</d2-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
value: ''
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,18 +0,0 @@
|
||||
<template>
|
||||
<d2-container type="card">
|
||||
<template slot="header">这个页面会被 keep-alive</template>
|
||||
<p class="d2-mt-0">在下面的输入框输入任意字符后,切换到其它页面,再回到此页时输入框文字保留,证明被缓存</p>
|
||||
<el-input v-model="value" placeholder="input here"></el-input>
|
||||
</d2-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'demo-playground-page-cache-on',
|
||||
data () {
|
||||
return {
|
||||
value: ''
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,42 +0,0 @@
|
||||
<template>
|
||||
<d2-container type="card">
|
||||
<template slot="header">
|
||||
<el-button
|
||||
size="mini"
|
||||
type="primary">
|
||||
props.id = {{id}}
|
||||
</el-button>
|
||||
</template>
|
||||
<p class="d2-mt-0">在下面的输入框输入任意字符后,切换到其它页面,再回到此页时输入框文字保留,证明被缓存</p>
|
||||
<p>注意:此页面根据不同 params 打开后数据不会混淆</p>
|
||||
<el-row :gutter="10">
|
||||
<el-col :span="12">
|
||||
<p>el-input</p>
|
||||
<el-input v-model="data.value" placeholder="input here" />
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<p>html input</p>
|
||||
<div class="el-input el-input--default">
|
||||
<input v-model="data.value" placeholder="input here" class="el-input__inner" />
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</d2-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'demo-playground-page-cache-params',
|
||||
props: {
|
||||
id: {
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
data: { value: '' }
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,19 +0,0 @@
|
||||
<template>
|
||||
<d2-container type="card" class="page-demo-playground-fullscreen">
|
||||
<template slot="header">全屏</template>
|
||||
<el-button type="primary" @click="toggle">
|
||||
toggle 切换全屏
|
||||
</el-button>
|
||||
</d2-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapActions } from 'vuex'
|
||||
export default {
|
||||
methods: {
|
||||
...mapActions('d2admin/fullscreen', [
|
||||
'toggle'
|
||||
])
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,87 +0,0 @@
|
||||
<template>
|
||||
<d2-container type="card" class="page">
|
||||
<template slot="header">
|
||||
<div class="colorful">{{grayActive ? 'GRAY' : 'COLORFUL'}}</div>
|
||||
</template>
|
||||
<el-button-group>
|
||||
<el-button @click="grayToggle">切换灰度模式</el-button>
|
||||
<el-button @click="graySet(true)">打开灰度模式</el-button>
|
||||
<el-button @click="graySet(false)">关闭灰度模式</el-button>
|
||||
<el-button @click="dialogVisible = true">模拟报错提示框</el-button>
|
||||
</el-button-group>
|
||||
<el-dialog
|
||||
title="错误"
|
||||
:visible.sync="dialogVisible"
|
||||
:append-to-body="true"
|
||||
width="30%"
|
||||
@open="handleDialogOpen"
|
||||
@closed="handleDialogClosed">
|
||||
<div
|
||||
style="
|
||||
text-align: center;
|
||||
line-height: 100px;
|
||||
color: #FFF;
|
||||
font-size: 64px;
|
||||
font-weight: bold;
|
||||
border-radius: 4px;
|
||||
background-color: #F56C6C;
|
||||
margin: -20px 0px;
|
||||
">
|
||||
Error
|
||||
</div>
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="dialogVisible = false" style="width: 100%;">
|
||||
我看到后面的内容已经变为灰度模式
|
||||
</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
</d2-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapState, mapMutations } from 'vuex'
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
dialogVisible: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState('d2admin/gray', {
|
||||
grayActive: 'active'
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
...mapMutations('d2admin/gray', {
|
||||
grayToggle: 'toggle',
|
||||
graySet: 'set'
|
||||
}),
|
||||
handleDialogOpen () {
|
||||
this.graySet(true)
|
||||
},
|
||||
handleDialogClosed () {
|
||||
this.graySet(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.page {
|
||||
.colorful {
|
||||
@extend %unable-select;
|
||||
line-height: 300px;
|
||||
font-size: 100px;
|
||||
font-weight: bold;
|
||||
color: #FFF;
|
||||
text-align: center;
|
||||
border-radius: 4px;
|
||||
border: 1px solid #333;
|
||||
background-color: #ffff00;
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='100%25' height='100%25' viewBox='0 0 1200 800'%3E%3Cdefs%3E%3CradialGradient id='a' cx='0' cy='800' r='800' gradientUnits='userSpaceOnUse'%3E%3Cstop offset='0' stop-color='%23ff8000'/%3E%3Cstop offset='1' stop-color='%23ff8000' stop-opacity='0'/%3E%3C/radialGradient%3E%3CradialGradient id='b' cx='1200' cy='800' r='800' gradientUnits='userSpaceOnUse'%3E%3Cstop offset='0' stop-color='%2300ff19'/%3E%3Cstop offset='1' stop-color='%2300ff19' stop-opacity='0'/%3E%3C/radialGradient%3E%3CradialGradient id='c' cx='600' cy='0' r='600' gradientUnits='userSpaceOnUse'%3E%3Cstop offset='0' stop-color='%239900ff'/%3E%3Cstop offset='1' stop-color='%239900ff' stop-opacity='0'/%3E%3C/radialGradient%3E%3CradialGradient id='d' cx='600' cy='800' r='600' gradientUnits='userSpaceOnUse'%3E%3Cstop offset='0' stop-color='%23ffff00'/%3E%3Cstop offset='1' stop-color='%23ffff00' stop-opacity='0'/%3E%3C/radialGradient%3E%3CradialGradient id='e' cx='0' cy='0' r='800' gradientUnits='userSpaceOnUse'%3E%3Cstop offset='0' stop-color='%23FF0000'/%3E%3Cstop offset='1' stop-color='%23FF0000' stop-opacity='0'/%3E%3C/radialGradient%3E%3CradialGradient id='f' cx='1200' cy='0' r='800' gradientUnits='userSpaceOnUse'%3E%3Cstop offset='0' stop-color='%230CF'/%3E%3Cstop offset='1' stop-color='%230CF' stop-opacity='0'/%3E%3C/radialGradient%3E%3C/defs%3E%3Crect fill='url(%23a)' width='1200' height='800'/%3E%3Crect fill='url(%23b)' width='1200' height='800'/%3E%3Crect fill='url(%23c)' width='1200' height='800'/%3E%3Crect fill='url(%23d)' width='1200' height='800'/%3E%3Crect fill='url(%23e)' width='1200' height='800'/%3E%3Crect fill='url(%23f)' width='1200' height='800'/%3E%3C/svg%3E");
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,148 +0,0 @@
|
||||
<template>
|
||||
<d2-container>
|
||||
<el-tabs>
|
||||
<el-tab-pane label="顶栏菜单">
|
||||
<el-button-group class="d2-mb">
|
||||
<el-button @click="handleHeaderSet">设置顶栏空菜单</el-button>
|
||||
<el-button @click="headerReset">恢复顶栏菜单</el-button>
|
||||
</el-button-group>
|
||||
<d2-highlight :code="JSON.stringify(header, null, 2)"/>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="侧栏菜单">
|
||||
<el-button-group class="d2-mb">
|
||||
<el-button @click="handleAsideSet">设置侧栏空菜单</el-button>
|
||||
<el-button @click="asideReset">恢复侧栏菜单</el-button>
|
||||
<el-button @click="asideTransitionToggle()">{{`${asideTransition ? '关闭' : '开启'}侧栏动画效果`}}</el-button>
|
||||
</el-button-group>
|
||||
<d2-highlight :code="JSON.stringify(aside, null, 2)"/>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</d2-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { cloneDeep } from 'lodash'
|
||||
import { mapState, mapMutations, mapActions } from 'vuex'
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
menuEmpty: [
|
||||
{
|
||||
title: '空菜单演示',
|
||||
icon: 'folder-o',
|
||||
children: [
|
||||
{
|
||||
title: '空菜单 1',
|
||||
children: [
|
||||
{ title: '空菜单 1-1' },
|
||||
{ title: '空菜单 1-2' }
|
||||
]
|
||||
},
|
||||
{ title: '空菜单 2' },
|
||||
{ title: '空菜单 3' }
|
||||
]
|
||||
}
|
||||
],
|
||||
headerChanged: false,
|
||||
asideChanged: false,
|
||||
headerBak: [],
|
||||
asideBak: []
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState('d2admin/menu', [
|
||||
'header',
|
||||
'aside',
|
||||
'asideTransition'
|
||||
])
|
||||
},
|
||||
created () {
|
||||
this.headerBak = cloneDeep(this.header)
|
||||
this.asideBak = cloneDeep(this.aside)
|
||||
},
|
||||
beforeDestroy () {
|
||||
if (this.headerChanged && this.asideChanged) {
|
||||
this.headerSet(this.headerBak)
|
||||
this.asideSet(this.asideBak)
|
||||
this.$notify({
|
||||
title: '菜单恢复',
|
||||
message: '对侧边栏和顶栏菜单的修改已经复原',
|
||||
type: 'success'
|
||||
})
|
||||
return
|
||||
}
|
||||
if (this.headerChanged) {
|
||||
this.headerSet(this.headerBak)
|
||||
this.$notify({
|
||||
title: '菜单恢复',
|
||||
message: '对顶栏菜单的修改已经复原',
|
||||
type: 'success'
|
||||
})
|
||||
return
|
||||
}
|
||||
if (this.asideChanged) {
|
||||
this.asideSet(this.asideBak)
|
||||
this.$notify({
|
||||
title: '菜单恢复',
|
||||
message: '对侧边栏菜单的修改已经复原',
|
||||
type: 'success'
|
||||
})
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
...mapMutations('d2admin/menu', [
|
||||
'headerSet',
|
||||
'asideSet'
|
||||
]),
|
||||
...mapActions('d2admin/menu', [
|
||||
'asideTransitionToggle'
|
||||
]),
|
||||
/**
|
||||
* 修改顶栏菜单
|
||||
*/
|
||||
handleHeaderSet () {
|
||||
this.headerChanged = true
|
||||
this.headerSet(this.menuEmpty)
|
||||
this.$notify({
|
||||
title: '菜单修改',
|
||||
message: '对顶栏菜单的修改已经生效',
|
||||
type: 'success'
|
||||
})
|
||||
},
|
||||
/**
|
||||
* 修改侧边栏菜单
|
||||
*/
|
||||
handleAsideSet () {
|
||||
this.asideChanged = true
|
||||
this.asideSet(this.menuEmpty)
|
||||
this.$notify({
|
||||
title: '菜单修改',
|
||||
message: '对侧边栏菜单的修改已经生效',
|
||||
type: 'success'
|
||||
})
|
||||
},
|
||||
/**
|
||||
* 恢复顶栏菜单
|
||||
*/
|
||||
headerReset () {
|
||||
this.headerSet(this.headerBak)
|
||||
this.$notify({
|
||||
title: '菜单恢复',
|
||||
message: '对顶栏菜单的修改已经复原',
|
||||
type: 'success'
|
||||
})
|
||||
},
|
||||
/**
|
||||
* 恢复侧边栏菜单
|
||||
*/
|
||||
asideReset () {
|
||||
this.asideSet(this.asideBak)
|
||||
this.$notify({
|
||||
title: '菜单恢复',
|
||||
message: '对侧边栏菜单的修改已经复原',
|
||||
type: 'success'
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,98 +0,0 @@
|
||||
<template>
|
||||
<d2-container type="card">
|
||||
<!-- 证明有缓存 -->
|
||||
<p class="d2-mt-0">在下面的输入框输入任意字符后,切换到其它页面,再回到此页时输入框文字保留,证明被缓存</p>
|
||||
<el-input v-model="value" placeholder="input here"></el-input>
|
||||
<!-- 页签操作 -->
|
||||
<p>关闭标签页</p>
|
||||
<el-button-group>
|
||||
<el-button @click="handleCloseCurrent">
|
||||
<d2-icon name="times"/> 当前
|
||||
</el-button>
|
||||
<el-button @click="handleCloseLeft">
|
||||
<d2-icon name="arrow-left"/> 左侧
|
||||
</el-button>
|
||||
<el-button @click="handleCloseRight">
|
||||
右侧 <d2-icon name="arrow-right"/>
|
||||
</el-button>
|
||||
<el-button @click="handleCloseOther">
|
||||
其它 <d2-icon name="times"/>
|
||||
</el-button>
|
||||
<el-button @click="closeAll">
|
||||
全部 <d2-icon name="times-circle"/>
|
||||
</el-button>
|
||||
</el-button-group>
|
||||
<p>刷新</p>
|
||||
<el-button-group>
|
||||
<el-button @click="handleCleanCacheAndRefreshCurrent">
|
||||
<d2-icon name="refresh"/>
|
||||
清空当前页缓存并刷新
|
||||
</el-button>
|
||||
<el-button @click="handleCleanCacheAndRefreshAll">
|
||||
<d2-icon name="refresh"/>
|
||||
清空所有缓存并刷新
|
||||
</el-button>
|
||||
</el-button-group>
|
||||
</d2-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapMutations, mapActions } from 'vuex'
|
||||
export default {
|
||||
name: 'demo-playground-store-page',
|
||||
data () {
|
||||
return {
|
||||
value: ''
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
...mapMutations('d2admin/page', [
|
||||
'keepAliveRemove',
|
||||
'keepAliveClean'
|
||||
]),
|
||||
...mapActions('d2admin/page', [
|
||||
'close',
|
||||
'closeLeft',
|
||||
'closeRight',
|
||||
'closeOther',
|
||||
'closeAll'
|
||||
]),
|
||||
// 关闭当前
|
||||
handleCloseCurrent () {
|
||||
this.close({
|
||||
tagName: this.$route.fullPath
|
||||
})
|
||||
},
|
||||
// 关闭左侧
|
||||
handleCloseLeft () {
|
||||
this.closeLeft({
|
||||
tagName: this.$route.fullPath
|
||||
})
|
||||
},
|
||||
// 关闭右侧
|
||||
handleCloseRight () {
|
||||
this.closeRight({
|
||||
tagName: this.$route.fullPath
|
||||
})
|
||||
},
|
||||
// 关闭其他
|
||||
handleCloseOther () {
|
||||
this.closeOther({
|
||||
tagName: this.$route.fullPath
|
||||
})
|
||||
},
|
||||
// 清空当前页缓存并刷新此页面
|
||||
async handleCleanCacheAndRefreshCurrent () {
|
||||
this.keepAliveRemove(this.$route.name)
|
||||
await this.$nextTick()
|
||||
this.$router.replace('/refresh')
|
||||
},
|
||||
// 清空所有的缓存并刷新此页面
|
||||
async handleCleanCacheAndRefreshAll () {
|
||||
this.keepAliveClean()
|
||||
await this.$nextTick()
|
||||
this.$router.replace('/refresh')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,39 +0,0 @@
|
||||
<template>
|
||||
<d2-container type="card">
|
||||
<el-radio-group v-model="currentValue" @change="set">
|
||||
<el-radio-button label="default"></el-radio-button>
|
||||
<el-radio-button label="medium"></el-radio-button>
|
||||
<el-radio-button label="small"></el-radio-button>
|
||||
<el-radio-button label="mini"></el-radio-button>
|
||||
</el-radio-group>
|
||||
</d2-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapState, mapActions } from 'vuex'
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
currentValue: ''
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState('d2admin/size', [
|
||||
'value'
|
||||
])
|
||||
},
|
||||
watch: {
|
||||
value: {
|
||||
handler (val) {
|
||||
this.currentValue = val
|
||||
},
|
||||
immediate: true
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
...mapActions('d2admin/size', [
|
||||
'set'
|
||||
])
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,74 +0,0 @@
|
||||
<template>
|
||||
<d2-container type="card" class="page">
|
||||
<template slot="header">主题</template>
|
||||
<el-table :data="list" v-bind="table">
|
||||
<el-table-column prop="name" align="center" width="260"/>
|
||||
<el-table-column label="预览" width="120">
|
||||
<div
|
||||
slot-scope="scope"
|
||||
class="theme-preview"
|
||||
:style="{'backgroundImage': `url(${$baseUrl}${scope.row.preview})`}">
|
||||
</div>
|
||||
</el-table-column>
|
||||
<el-table-column prop="address" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-button v-if="activeName === scope.row.name" type="success" icon="el-icon-check" round>已激活</el-button>
|
||||
<el-button v-else round @click="handleSelectTheme(scope.row.name)">使用</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div>
|
||||
<p>尝试激活一个不存在的主题(主题不存在 <d2-icon name="arrow-right"/> 默认主题)</p>
|
||||
<el-button type="danger" @click="handleSelectTheme('err-theme')">
|
||||
<d2-icon name="hand-o-right" class="d2-mr-10"/>
|
||||
尝试激活主题 'err-theme'
|
||||
</el-button>
|
||||
</div>
|
||||
<el-button
|
||||
slot="footer"
|
||||
type="primary"
|
||||
size="small">
|
||||
当前激活主题 {{activeName}}
|
||||
</el-button>
|
||||
</d2-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapState, mapActions } from 'vuex'
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
table: {
|
||||
showHeader: false,
|
||||
border: true
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState('d2admin/theme', [
|
||||
'list',
|
||||
'activeName'
|
||||
])
|
||||
},
|
||||
methods: {
|
||||
...mapActions('d2admin/theme', [
|
||||
'set'
|
||||
]),
|
||||
handleSelectTheme (name) {
|
||||
this.set(name)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.page {
|
||||
.theme-preview {
|
||||
height: 50px;
|
||||
width: 100px;
|
||||
border-radius: 4px;
|
||||
background-size: cover;
|
||||
border: 1px solid $color-border-1;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,26 +0,0 @@
|
||||
<template>
|
||||
<d2-container type="card">
|
||||
<template slot="header">
|
||||
当前状态 {{active ? '开启过渡动画' : '关闭过渡动画'}}
|
||||
</template>
|
||||
<el-button type="primary" @click="set(!active)">
|
||||
{{active ? '关闭页面过渡动画' : '打开页面过渡动画'}}
|
||||
</el-button>
|
||||
</d2-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapState, mapActions } from 'vuex'
|
||||
export default {
|
||||
computed: {
|
||||
...mapState('d2admin/transition', [
|
||||
'active'
|
||||
])
|
||||
},
|
||||
methods: {
|
||||
...mapActions('d2admin/transition', [
|
||||
'set'
|
||||
])
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,23 +0,0 @@
|
||||
<template>
|
||||
<d2-container>
|
||||
<p class="d2-mt-0">useragent</p>
|
||||
<el-input :value="uaData.ua"></el-input>
|
||||
<p>格式化数据 in vuex: state.d2admin.ua.data</p>
|
||||
<d2-highlight :code="uaStr"/>
|
||||
</d2-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapState } from 'vuex'
|
||||
export default {
|
||||
computed: {
|
||||
...mapState('d2admin/ua', {
|
||||
uaData: 'data'
|
||||
}),
|
||||
uaStr () {
|
||||
const { browser, engine, os, device, cpu } = this.uaData
|
||||
return JSON.stringify({ browser, engine, os, device, cpu }, null, 2)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,82 +0,0 @@
|
||||
<template>
|
||||
<d2-container>
|
||||
<template slot="header">剪贴板访问</template>
|
||||
<el-row :gutter="10">
|
||||
<el-col :span="12">
|
||||
<div class="d2-mb">
|
||||
<el-input v-model="text" style="width: 200px;"></el-input>
|
||||
<el-button class="d2-ml" @click="copyText()">将左侧输入框内的文字复制进剪贴板</el-button>
|
||||
</div>
|
||||
<el-button @click="copyHtml()">将 <span v-html="html"></span> 连带样式一起复制进剪贴板,然后去 Word 文档内粘贴</el-button>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-alert
|
||||
class="d2-mb"
|
||||
title="在 IE 浏览器或者高版本 Chrome 下你才可以通过下面这两个按钮获取剪贴板数据"
|
||||
type="warning"
|
||||
show-icon>
|
||||
</el-alert>
|
||||
<div class="d2-mb">
|
||||
<el-tooltip content="需要 IE 浏览器" placement="top">
|
||||
<el-button @click="readText">readText( )</el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="需要 IE 浏览器" placement="top">
|
||||
<el-button @click="read">read( )</el-button>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
<el-input type="textarea" placeholder="在这里检验你的剪贴板 ( text/plain 数据 )"></el-input>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</d2-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as clipboard from 'clipboard-polyfill'
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
text: 'Hello ~',
|
||||
html: '<span style="background-color: #19be6b; color: #f8f8f9;">Hello</span><span style="background-color: #495060; color: #f8f8f9;">World</span>'
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
copyText () {
|
||||
clipboard.writeText(this.text)
|
||||
},
|
||||
copyHtml () {
|
||||
var dt = new clipboard.DT()
|
||||
dt.setData('text/html', this.html)
|
||||
clipboard.write(dt)
|
||||
},
|
||||
readText () {
|
||||
clipboard.readText().then((res) => {
|
||||
this.$message({
|
||||
message: '读取成功 返回结果请查看控制台',
|
||||
type: 'success'
|
||||
})
|
||||
}, err => {
|
||||
console.log(err)
|
||||
this.$message({
|
||||
message: '错误信息已经打印到控制台',
|
||||
type: 'error'
|
||||
})
|
||||
})
|
||||
},
|
||||
read () {
|
||||
clipboard.read().then((res) => {
|
||||
console.log(res)
|
||||
this.$message({
|
||||
message: '读取成功 返回结果请查看控制台',
|
||||
type: 'success'
|
||||
})
|
||||
}, (err) => {
|
||||
console.log(err)
|
||||
this.$message({
|
||||
message: '错误信息已经打印到控制台',
|
||||
type: 'error'
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,73 +0,0 @@
|
||||
<template>
|
||||
<d2-container>
|
||||
<template slot="header">日期计算</template>
|
||||
<h1 class="d2-mt-0">解析</h1>
|
||||
<el-row :gutter="20" class="d2-mt">
|
||||
<el-col :span="6"><el-card shadow="never" class="d2-mb"><d2-highlight slot="header" :code="`// 当前时间\ndayjs()`"/>{{dayjs()}}</el-card></el-col>
|
||||
<el-col :span="6"><el-card shadow="never" class="d2-mb"><d2-highlight slot="header" :code="`// 时间字符串\ndayjs('1995-12-25')`"/>{{dayjs('1995-12-25')}}</el-card></el-col>
|
||||
<el-col :span="6"><el-card shadow="never" class="d2-mb"><d2-highlight slot="header" :code="`// Unix 时间戳 (毫秒)\ndayjs(1318781876406)`"/>{{dayjs(1318781876406)}}</el-card></el-col>
|
||||
<el-col :span="6"><el-card shadow="never" class="d2-mb"><d2-highlight slot="header" :code="`// Date 对象\ndayjs(new Date(2018, 8, 18))`"/>{{dayjs(new Date(2018, 8, 18))}}</el-card></el-col>
|
||||
<el-col :span="6"><el-card shadow="never"><d2-highlight slot="header" :code="`// 复制\ndayjs().clone()`"/>{{dayjs().clone()}}</el-card></el-col>
|
||||
<el-col :span="6"><el-card shadow="never"><d2-highlight slot="header" :code="`// 检测是否是一个有效的时间\ndayjs().isValid()`"/>{{dayjs().isValid()}}</el-card></el-col>
|
||||
</el-row>
|
||||
<h1>获取</h1>
|
||||
<el-row :gutter="20" class="d2-mt">
|
||||
<el-col :span="6"><el-card shadow="never" class="d2-mb"><d2-highlight slot="header" :code="`// 获取年\ndayjs().year()`"/>{{dayjs().year()}}</el-card></el-col>
|
||||
<el-col :span="6"><el-card shadow="never" class="d2-mb"><d2-highlight slot="header" :code="`// 获取月\ndayjs().month()`"/>{{dayjs().month()}}</el-card></el-col>
|
||||
<el-col :span="6"><el-card shadow="never" class="d2-mb"><d2-highlight slot="header" :code="`// 获取日\ndayjs().date()`"/>{{dayjs().date()}}</el-card></el-col>
|
||||
<el-col :span="6"><el-card shadow="never" class="d2-mb"><d2-highlight slot="header" :code="`// 获取星期\ndayjs().day()`"/>{{dayjs().day()}}</el-card></el-col>
|
||||
<el-col :span="6"><el-card shadow="never"><d2-highlight slot="header" :code="`// 获取小时\ndayjs().hour()`"/>{{dayjs().hour()}}</el-card></el-col>
|
||||
<el-col :span="6"><el-card shadow="never"><d2-highlight slot="header" :code="`// 获取分钟\ndayjs().minute()`"/>{{dayjs().minute()}}</el-card></el-col>
|
||||
<el-col :span="6"><el-card shadow="never"><d2-highlight slot="header" :code="`// 获取秒\ndayjs().second()`"/>{{dayjs().second()}}</el-card></el-col>
|
||||
<el-col :span="6"><el-card shadow="never"><d2-highlight slot="header" :code="`// 获取毫秒\ndayjs().millisecond()`"/>{{dayjs().millisecond()}}</el-card></el-col>
|
||||
</el-row>
|
||||
<h1>设置</h1>
|
||||
<el-row :gutter="20" class="d2-mt">
|
||||
<el-col :span="8"><el-card shadow="never"><d2-highlight slot="header" :code="`// 设置月份\ndayjs().set('month', 6).month()`"/>{{dayjs().set('month', 6).month()}}</el-card></el-col>
|
||||
<el-col :span="8"><el-card shadow="never"><d2-highlight slot="header" :code="`// 设置秒\ndayjs().set('second', 30).second()`"/>{{dayjs().set('second', 30).second()}}</el-card></el-col>
|
||||
<el-col :span="8"><el-card shadow="never"><d2-highlight slot="header" :code="`// 设置小时\ndayjs().set('hour', 4).hour()`"/>{{dayjs().set('hour', 4).hour()}}</el-card></el-col>
|
||||
</el-row>
|
||||
<h1>操作</h1>
|
||||
<el-row :gutter="20" class="d2-mt">
|
||||
<el-col :span="12"><el-card shadow="never" class="d2-mb"><d2-highlight slot="header" :code="`// 增加\ndayjs().add(1, 'day').format('YYYY年M月D日 HH:mm:ss')`"/>{{dayjs().add(1, 'day').format('YYYY年M月D日 HH:mm:ss')}}</el-card></el-col>
|
||||
<el-col :span="12"><el-card shadow="never" class="d2-mb"><d2-highlight slot="header" :code="`// 减少\ndayjs().subtract(7, 'year').format('YYYY年M月D日 HH:mm:ss')`"/>{{dayjs().subtract(7, 'year').format('YYYY年M月D日 HH:mm:ss')}}</el-card></el-col>
|
||||
<el-col :span="12"><el-card shadow="never"><d2-highlight slot="header" :code="`// 开头时间\ndayjs().startOf('year').format('YYYY年M月D日 HH:mm:ss')`"/>{{dayjs().startOf('year').format('YYYY年M月D日 HH:mm:ss')}}</el-card></el-col>
|
||||
<el-col :span="12"><el-card shadow="never"><d2-highlight slot="header" :code="`// 末尾时间\ndayjs().endOf('month').format('YYYY年M月D日 HH:mm:ss')`"/>{{dayjs().endOf('month').format('YYYY年M月D日 HH:mm:ss')}}</el-card></el-col>
|
||||
</el-row>
|
||||
<h1>显示</h1>
|
||||
<el-row :gutter="20" class="d2-mt">
|
||||
<el-col :span="12"><el-card shadow="never" class="d2-mb"><d2-highlight slot="header" :code="`// 格式化\ndayjs().format('YYYY-M-D HH:mm:ss')`"/>{{dayjs().format('YYYY-M-D HH:mm:ss')}}</el-card></el-col>
|
||||
<el-col :span="12"><el-card shadow="never" class="d2-mb"><d2-highlight slot="header" :code="`// 时间差\ndayjs().diff(dayjs().subtract(1, 'day'), 'days')`"/>{{dayjs().diff(dayjs().subtract(1, 'day'), 'days')}}</el-card></el-col>
|
||||
<el-col :span="12"><el-card shadow="never" class="d2-mb"><d2-highlight slot="header" :code="`// Unix 时间戳 (毫秒)\ndayjs().valueOf()`"/>{{dayjs().valueOf()}}</el-card></el-col>
|
||||
<el-col :span="12"><el-card shadow="never" class="d2-mb"><d2-highlight slot="header" :code="`// Unix 时间戳 (秒)\ndayjs().unix()`"/>{{dayjs().unix()}}</el-card></el-col>
|
||||
<el-col :span="12"><el-card shadow="never" class="d2-mb"><d2-highlight slot="header" :code="`// 天数 (月)\ndayjs().daysInMonth()`"/>{{dayjs().daysInMonth()}}</el-card></el-col>
|
||||
<el-col :span="12"><el-card shadow="never" class="d2-mb"><d2-highlight slot="header" :code="`// Date 对象\ndayjs().toDate()`"/>{{dayjs().toDate()}}</el-card></el-col>
|
||||
<!-- <el-col :span="12"><el-card shadow="never" class="d2-mb"><d2-highlight slot="header" :code="`// 数组\ndayjs().toArray()`"/>{{dayjs().toArray()}}</el-card></el-col> -->
|
||||
<el-col :span="12"><el-card shadow="never" class="d2-mb"><d2-highlight slot="header" :code="`// 序列化 Dayjs 对象时会返回 ISO 8601 格式的字符串\ndayjs().toJSON()`"/>{{dayjs().toJSON()}}</el-card></el-col>
|
||||
<el-col :span="12"><el-card shadow="never" class="d2-mb"><d2-highlight slot="header" :code="`// ISO 8601 字符串\ndayjs().toISOString()`"/>{{dayjs().toISOString()}}</el-card></el-col>
|
||||
<el-col :span="12"><el-card shadow="never" class="d2-mb"><d2-highlight slot="header" :code="`// 字符串\ndayjs().toString()`"/>{{dayjs().toString()}}</el-card></el-col>
|
||||
<!-- <el-col :span="24"><el-card shadow="never"><d2-highlight slot="header" :code="`// 对象\ndayjs().toObject()`"/>{{dayjs().toObject()}}</el-card></el-col> -->
|
||||
</el-row>
|
||||
<h1>查询</h1>
|
||||
<el-row :gutter="20" class="d2-mt">
|
||||
<el-col :span="12"><el-card shadow="never" class="d2-mb"><d2-highlight slot="header" :code="`// 是否之前\ndayjs().isBefore(dayjs().add(1, 'day'))`"/>{{dayjs().isBefore(dayjs().add(1, 'day'))}}</el-card></el-col>
|
||||
<el-col :span="12"><el-card shadow="never" class="d2-mb"><d2-highlight slot="header" :code="`// 是否之前\ndayjs().isBefore(dayjs().subtract(1, 'day'))`"/>{{dayjs().isBefore(dayjs().subtract(1, 'day'))}}</el-card></el-col>
|
||||
<el-col :span="12"><el-card shadow="never" class="d2-mb"><d2-highlight slot="header" :code="`// 是否相同\ndayjs().isSame(dayjs())`"/>{{dayjs().isSame(dayjs())}}</el-card></el-col>
|
||||
<el-col :span="12"><el-card shadow="never" class="d2-mb"><d2-highlight slot="header" :code="`// 是否相同\ndayjs().isSame(dayjs().add(1, 'day'))`"/>{{dayjs().isSame(dayjs().add(1, 'day'))}}</el-card></el-col>
|
||||
<el-col :span="12"><el-card shadow="never"><d2-highlight slot="header" :code="`// 是否之后\ndayjs().isAfter(dayjs().add(1, 'day'))`"/>{{dayjs().isAfter(dayjs().add(1, 'day'))}}</el-card></el-col>
|
||||
<el-col :span="12"><el-card shadow="never"><d2-highlight slot="header" :code="`// 是否之后\ndayjs().isAfter(dayjs().subtract(1, 'day'))`"/>{{dayjs().isAfter(dayjs().subtract(1, 'day'))}}</el-card></el-col>
|
||||
</el-row>
|
||||
<d2-link-btn slot="footer" title="依赖" link="https://github.com/iamkun/dayjs"/>
|
||||
</d2-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import dayjs from 'dayjs'
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
dayjs
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,72 +0,0 @@
|
||||
<template>
|
||||
<d2-container type="card">
|
||||
<template slot="header">导出表格</template>
|
||||
<div class="d2-mb">
|
||||
<el-button type="primary" @click="exportCsv">
|
||||
<d2-icon name="download"/>
|
||||
导出 CSV
|
||||
</el-button>
|
||||
<el-button type="primary" @click="exportExcel">
|
||||
<d2-icon name="download"/>
|
||||
导出 Excel
|
||||
</el-button>
|
||||
</div>
|
||||
<el-table v-bind="table" style="width: 100%">
|
||||
<el-table-column
|
||||
v-for="(item, index) in table.columns"
|
||||
:key="index"
|
||||
:prop="item.prop"
|
||||
:label="item.label">
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</d2-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Vue from 'vue'
|
||||
import pluginExport from '@d2-projects/vue-table-export'
|
||||
Vue.use(pluginExport)
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
table: {
|
||||
columns: [
|
||||
{ label: 'ID', prop: 'id' },
|
||||
{ label: '名称', prop: 'name' },
|
||||
{ label: '创建日期', prop: 'creatDate' },
|
||||
{ label: '地址', prop: 'address' },
|
||||
{ label: '邮编', prop: 'zip' }
|
||||
],
|
||||
data: [
|
||||
{ id: 1, name: 'Lucy', creatDate: '2020-05-07', address: 'Address', zip: '000000' }
|
||||
],
|
||||
size: 'mini',
|
||||
stripe: true,
|
||||
border: true
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
exportCsv (params = {}) {
|
||||
this.$export.csv({
|
||||
columns: this.table.columns,
|
||||
data: this.table.data
|
||||
})
|
||||
.then(() => {
|
||||
this.$message('导出CSV成功')
|
||||
})
|
||||
},
|
||||
exportExcel () {
|
||||
this.$export.excel({
|
||||
columns: this.table.columns,
|
||||
data: this.table.data,
|
||||
header: '导出 Excel',
|
||||
merges: ['A1', 'E1']
|
||||
})
|
||||
.then(() => {
|
||||
this.$message('导出表格成功')
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,47 +0,0 @@
|
||||
<template>
|
||||
<d2-container type="card">
|
||||
<template slot="header">导出文本</template>
|
||||
<el-input
|
||||
type="textarea"
|
||||
:autosize="{minRows: 2, maxRows: 4}"
|
||||
placeholder="请输入内容 然后点击保存按钮导出文本文档"
|
||||
v-model="text">
|
||||
</el-input>
|
||||
<div class="d2-mt">
|
||||
<el-button type="primary" @click="exportTxt">
|
||||
<d2-icon name="download"/>
|
||||
保存为 txt
|
||||
</el-button>
|
||||
</div>
|
||||
</d2-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Vue from 'vue'
|
||||
import pluginExport from '@d2-projects/vue-table-export'
|
||||
Vue.use(pluginExport)
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
text: ''
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
exportTxt () {
|
||||
// 校验是不是空
|
||||
if (this.text === '') {
|
||||
this.$message('虽然可以为空 但是出于体验不建议这样 还是写点东西吧')
|
||||
return
|
||||
}
|
||||
// 导出
|
||||
this.$export.txt({
|
||||
text: this.text,
|
||||
title: '文本'
|
||||
})
|
||||
.then(() => {
|
||||
this.$message('导出文本成功')
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,62 +0,0 @@
|
||||
<template>
|
||||
<d2-container type="card">
|
||||
<template slot="header">
|
||||
<el-button @click="download">
|
||||
<d2-icon name="download"/>
|
||||
下载演示 .csv 表格
|
||||
</el-button>
|
||||
</template>
|
||||
<div class="d2-mb">
|
||||
<el-upload :before-upload="handleUpload" action="default">
|
||||
<el-button type="success">
|
||||
<d2-icon name="file-o"/>
|
||||
选择要导入的 .csv 表格
|
||||
</el-button>
|
||||
</el-upload>
|
||||
</div>
|
||||
<el-table v-bind="table">
|
||||
<el-table-column
|
||||
v-for="(item, index) in table.columns"
|
||||
:key="index"
|
||||
:prop="item.prop"
|
||||
:label="item.label">
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</d2-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Vue from 'vue'
|
||||
import pluginImport from '@d2-projects/vue-table-import'
|
||||
Vue.use(pluginImport)
|
||||
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
table: {
|
||||
columns: [],
|
||||
data: [],
|
||||
size: 'mini',
|
||||
stripe: true,
|
||||
border: true
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleUpload (file) {
|
||||
this.$import.csv(file)
|
||||
.then(res => {
|
||||
this.table.columns = Object.keys(res.data[0]).map(e => ({
|
||||
label: e,
|
||||
prop: e
|
||||
}))
|
||||
this.table.data = res.data
|
||||
})
|
||||
return false
|
||||
},
|
||||
download () {
|
||||
this.$open('https://file.d2.pub/document/d2-admin/demo-csv.csv')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,64 +0,0 @@
|
||||
<template>
|
||||
<d2-container type="card">
|
||||
<template slot="header">
|
||||
<el-button @click="download">
|
||||
<d2-icon name="download"/>
|
||||
下载演示 .xlsx 表格
|
||||
</el-button>
|
||||
</template>
|
||||
<div class="d2-mb">
|
||||
<el-upload :before-upload="handleUpload" action="default">
|
||||
<el-button type="success">
|
||||
<d2-icon name="file-o"/>
|
||||
选择要导入的 .xlsx 表格
|
||||
</el-button>
|
||||
</el-upload>
|
||||
</div>
|
||||
<el-table v-bind="table">
|
||||
<el-table-column
|
||||
v-for="(item, index) in table.columns"
|
||||
:key="index"
|
||||
:prop="item.prop"
|
||||
:label="item.label">
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</d2-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Vue from 'vue'
|
||||
import pluginImport from '@d2-projects/vue-table-import'
|
||||
Vue.use(pluginImport)
|
||||
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
table: {
|
||||
columns: [],
|
||||
data: [],
|
||||
size: 'mini',
|
||||
stripe: true,
|
||||
border: true
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleUpload (file) {
|
||||
this.$import.xlsx(file)
|
||||
.then(({ header, results }) => {
|
||||
this.table.columns = header.map(e => {
|
||||
return {
|
||||
label: e,
|
||||
prop: e
|
||||
}
|
||||
})
|
||||
this.table.data = results
|
||||
})
|
||||
return false
|
||||
},
|
||||
download () {
|
||||
this.$open('https://file.d2.pub/document/d2-admin/demo-table.xlsx')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,21 +0,0 @@
|
||||
<template>
|
||||
<d2-container type="ghost">
|
||||
<d2-module-index-banner slot="header" v-bind="banner"/>
|
||||
<d2-module-index-menu :menu="menu"/>
|
||||
</d2-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import menu from '@/menu/modules/demo-plugins'
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
menu,
|
||||
banner: {
|
||||
title: 'PLUGIN',
|
||||
subTitle: 'D2Admin 集成了许多实用插件'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,54 +0,0 @@
|
||||
<template>
|
||||
<d2-container>
|
||||
<template slot="header">
|
||||
<div class="d2-mb">Cookie 读写</div>
|
||||
<el-alert
|
||||
title="建议"
|
||||
type="warning"
|
||||
description="建议使用 util 内的 cookies 对象,这样会在存储和读取时统一增加前缀,方便对 cookie 统一管理"
|
||||
show-icon>
|
||||
</el-alert>
|
||||
</template>
|
||||
<p class="d2-mt-0">基本读写删</p>
|
||||
<el-button type="primary" @click="set('demo-user-name', 'demo-user')">set('demo-user-name', 'normalValue')</el-button>
|
||||
<el-button type="info" @click="get('demo-user-name')">get('demo-user-name')</el-button>
|
||||
<el-button type="error" @click="remove('demo-user-name')">remove('demo-user-name')</el-button>
|
||||
<p>设置有效期</p>
|
||||
<el-button type="primary" @click="setExpires('demo-user-pwd', '123456789', 1)">设置 'demo-user-pwd' 有效期为一天</el-button>
|
||||
<el-button type="info" @click="get('demo-user-pwd')">get('demo-user-pwd')</el-button>
|
||||
<el-button type="error" @click="remove('demo-user-pwd')">remove('demo-user-pwd')</el-button>
|
||||
<p>获取所有可以获得的数据</p>
|
||||
<el-button type="info" @click="getAll">getAll</el-button>
|
||||
</d2-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import util from '@/libs/util.js'
|
||||
export default {
|
||||
methods: {
|
||||
set (name = 'default-name', value = 'default-value') {
|
||||
util.cookies.set(name, value)
|
||||
this.$message.info(`设置数据 ${name} = ${value}`)
|
||||
},
|
||||
setExpires (name = 'default-name', value = 'default-value', expires = 1) {
|
||||
util.cookies.set(name, value, {
|
||||
expires
|
||||
})
|
||||
this.$message.info(`设置数据 ${name} = ${value} 有效期 ${expires} 天`)
|
||||
},
|
||||
get (name = 'default-name') {
|
||||
const value = util.cookies.get(name)
|
||||
this.$message.info(`获取数据 ${name} = ${value}`)
|
||||
},
|
||||
getAll () {
|
||||
const value = util.cookies.getAll()
|
||||
console.log(value)
|
||||
this.$message.info('结果已经打印到控制台')
|
||||
},
|
||||
remove (name = 'default-name') {
|
||||
util.cookies.remove(name)
|
||||
this.$message.info(`删除数据 ${name}`)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
Reference in New Issue
Block a user