32 KiB
title, date, author
| title | date | author |
|---|---|---|
| Vue | 2021-03-23 10:30:31 | 文永达 |
Vue
Vite
官方文档
vite.config.js配置
src设置@别名
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
const { resolve } = require('path')
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue()],
resolve:{
alias:{
'@': resolve('src')
}
}
})
vite.config.ts 引入 path 模块注意点
-
安装
@types/node -
在
tsconfig.node.json配置"compilerOptions": { ... "allowSyntheticDefaultTmports": true }
npm包管理器
# 淘宝镜像
npm config set registry http://registry.npm.taobao.org/
# 查看镜像
npm config get registry
CentOS7安装node js
# 首先下载nodejs安装包
# 解压 注意这不是gz压缩
tar -xvf node-v14.18.1-linux-x64.tar.xz
mv node-v14.18.1-linux-x64.tar.xz /usr/node
vim /etc/profile
# node
export NODE_HOME=/usr/node
export PATH=$PATH:$NODE_HOME/bin
source /etc/profile
# 查看node 版本
node -v
npm -v
# 安装yarn
npm install -g yarn
# 软连接,防止找不到环境
ln -s "/usr/node/bin/node" "/usr/local/bin/node"
ln -s "/usr/node/bin/npm" "/usr/local/bin/npm"
ln -s "/usr/node/bin/yarn" "/usr/local/bin/yarn"
yarn包管理器
# PowerShell yarn : 无法加载文件 C:\Users\Admin\AppData\Roaming\npm\yarn.ps1,因为在此系统因为在此系统上禁止运行脚本。
# 以管理员方式运行powershell
set-ExecutionPolicy RemoteSigned
# 查看当前镜像
yarn config get registry
# https://registry.yarnpkg.com
# 更换镜像
yarn config set registry https://registry.yarnpkg.com
# 查看镜像是否成功
yarn config get registry
# 全局安装PTE脚手架
yarn global add generator-pte-cli
# 安装依赖
yarn
# 运行项目
yarn dev # yarn run dev
# 部署
# 具体看 package.json
yarn deploy
yarn build
# 移除依赖
yarn remove pte-ui
# 安装依赖
yarn add pte-ui@2.1.54
安装node-sass
# 安装gyp
npm install -g node-gyp
npm config set python python2.7
npm config set msvs_version 2017
yarn
Vue CLI
安装
npm install -g @vue/cli
yarn global add @vue/cli
vue --version
升级
npm upadte -g @vue/cli
yarn global upgrade --latest @vue/cli
创建一个项目
vue create hello-world #创建一个名叫 hello-world 的 vue cli项目
配置全局环境变量
.env 全局默认配置文件,不论什么环境都会加载合并
.env.development 开发环境下的配置文件
.env.production 生产环境下的配置文件
属性名必须以VUE_APP_开头
.env.development
VUE_APP_URL=''
文件的加载
根据启动命令vue会自动加载对应的环境,vue是根据文件名进行加载的,所以上面说“不要乱起名,也无需专门控制加载哪个文件”
比如执行npm run serve命令,会自动加载.env.development文件,也有可能是npm run dev,这个得看package.json配置的是啥,具体看下面package.json配置
可通过process.env属性 (全局属性)
.env有的,.env.development也有,就会优先.env.development,.env.development没有的,.env有的,就会有.env的
vue.config.js配置
src设置@别名
module.exports = {
chainWebpack: config => {
config.resolve.alias
.set('@', resolve("src"))
}
}
端口设置
module.exports = {
devServer: {
port: 9090
}
}
跨域代理
module.exports = {
devServer: {
proxy: {
'/api': {
target: 'http://127.0.0.1:9001',
ws: true,
changeOrigin: true,
pathRewrite: {
'^/api': ''
}
}
}
}
}
package.json配置
环境配置
{
"scripts": {
"start": "vue-cli-service serve --open --mode production",
"dev": "vue-cli-service serve --open",
"build": "vue-cli-service build",
"build:prod": "vue-cli-service build --mode production",
"lint": "vue-cli-service lint --fix",
"upload": "vue-cli-service ssh",
"test:unit": "vue-cli-service test:unit",
"test:e2e": "vue-cli-service test:e2e --mode development"
}
}
scripts中dev 说明 需要用 npm run dev 来启动开发环境
如果是serve则是 npm run serve,可以手动添加serve
"scripts": {
"start": "vue-cli-service serve --open --mode production",
"dev": "vue-cli-service serve --open",
"serve": "vue-cli-service serve --open",
"build": "vue-cli-service build",
"build:prod": "vue-cli-service build --mode production",
"lint": "vue-cli-service lint --fix",
"upload": "vue-cli-service ssh",
"test:unit": "vue-cli-service test:unit",
"test:e2e": "vue-cli-service test:e2e --mode development"
}
Axios
安装
npm install axios
yarn add axios
创建实例
// MyAxios.js
import axios from 'axios'
const instance = axios.create({
baseURL: 'http://localhost:8080',
timeout: 3000
})
export default instance
// demoApi.js
import axios from '@/utils/MyAxios'
import Qs from 'qs'
export const findList = () => {
return axios({
url: '',
method: 'get',
params: {
}
})
}
export const add = (data) => {
return axios({
url: '',
method: 'post',
//axios默认contentType为application/json springmvc默认是application/x-www-form-urlencoded
//需添加请求头
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
//并且数据需要转换成js对象
data: Qs.stringify(data)
})
}
TypeScript
基础类型
布尔值
let isDone: boolean = false;
数字
let decLiteral: number = 6;
let hexLiteral: number = 0xf00d;
let binaryLiteral: number = 0b1010;
let octalLiteral: number = 0o744;
字符串
let name: string = "bob";
name = 'smith';
还可以使用模版字符串,它可以定义多行文本和内嵌表达式。 这种字符串是被反引号包围( ```),并且以${ expr }这种形式嵌入表达式
let name: string = `Gene`;
let age: number = 37;
let sentence: string = `Hello , my name is ${ name }.
I'll be ${ age + 1 } years old next month.`;
这与下面定义相同
let sentence: string = "Hello, my name is " + name + ".\n\n" +
"I'll be " + (age + 1) + " years old next month.";
数组
可以在元素类型后面接上[],表示由此类型元素组成的一个数组:
let list: number[] = [1, 2, 3];
或者
let list: Array<number> = [1, 2, 3];
元组
元组类型允许表示一个已知元素类型和类型的数组,各元素的类型不必相同。比如,你可以定义一对值分别为string和number类型的元组。
let x: [string, number];
x = ['hello', 10];
枚举
使用enum类型可以为一组数组赋予友好的名字。
enum Color {Red, Green, Blue}
let c: Color = Color.Green;
默认情况下,从0开始为元素编号。 你也可以手动的指定成员的数值。 例如,我们将上面的例子改成从 1开始编号:
enum Color {Red = 1, Green, Blue}
let c: Color = Color.Green;
或者,全部都采用手动赋值:
enum Color {Red = 1, Green = 2, Blue = 4}
let c: Color = Color.Green;
枚举类型提供的一个便利是你可以由枚举的值得到它的名字。 例如,我们知道数值为2,但是不确定它映射到Color的哪个名字,我们可以查找相应的名字:
enum Color {Red = 1, Green, Blue}
let colorName: string = Color[2];
console.log(colorName); // 显示'Green'因为上面代码里它的值是2
Any
不希望类型检查器对这些值进行检查而是直接让它们通过编译阶段的检查。
那么可以使用 any类型来标记这些变量:
let notSure: any = 4;
notSure = "maybe a string instead";
notSure = false; // okay, definitely a boolean
在对现有代码进行改写的时候,any类型是十分有用的,它允许你在编译时可选择地包含或移除类型检查。 你可能认为 Object有相似的作用,就像它在其它语言中那样。 但是 Object类型的变量只是允许你给它赋任意值 - 但是却不能够在它上面调用任意的方法,即便它真的有这些方法:
let notSure: any = 4;
notSure.ifItExists(); // okay, ifItExists might exist at runtime
notSure.toFixed(); // okay, toFixed exists (but the compiler doesn't check)
let prettySure: Object = 4;
prettySure.toFixed(); // Error: Property 'toFixed' doesn't exist on type 'Object'.
当只知道一部分数据的类型时,any类型也是有用的。比如,有一个数组,它包含了不同类型的数据:
let list: any[] = [1, true, "free"];
console.log(list[1]); // true
list[1] = 100; // 100
比较像元组
Void
void类型与any类型相反,它表示没有任何类型。当一个函数没有返回值时,通常会见到其返回类型是void:
function warnUser(): void {
console.log("This is my warning message");
}
声明一个void类型的变量没有什么大用,因为你只能为它赋予undefinded和null:
let unusable: void = undefin
VueRouter
Vuex
Vuex是一个专为Vue.js应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
状态(state)通俗说就是数据(data)。
可用于父子组件数据传值。最主要用于解决兄弟组件数据传值,以往通过将数据存储到localStorage中。
安装
yarn add vuex
state
state相当于组件中的data,专门用来存放全局的数据
在src下创建 store文件夹
创建index.js文件
import { createStore } from 'vuex';
export default createStore({
// state相当于组件中的data,专门用来存放全局的数据
state: {
num: 0
},
//
getters: {},
//
mutations: {
increment (state) {
state.num++
}
},
})
修改入口文件main.js
import { createApp } from 'vue'
import App from './App.vue'
// 引入store
import store from '@/store'
createApp(App).use(store).mount('#app')
在src下创建views文件夹
创建About.vue
<template>
<div>
<h2>About 页面的 数字: {{ num }}</h2>
</div>
</template>
<script>
export default {
// 计算属性
computed: {
num() {
return this.$store.state.num
}
}
}
</script>
<style>
</style>
创建Home.vue
<template>
<div>
<h2>Home 页面的 数字: {{ $store.state.num }}</h2>
</div>
</template>
<script>
export default {
data() {
return{
}
},
}
</script>
<style>
</style>
在components文件夹下创建Btn.vue
<template>
<div>
<button @click="changeNum">点击加1</button>
</div>
</template>
<script>
export default {
methods: {
changeNum() {
// 改变状态
执行mutations下increment
this.$store.commit('increment')
}
}
}
</script>
<style>
</style>
修改主组件App.vue
<script>
// This starter template is using Vue 3 <script setup> SFCs
// Check out https://v3.vuejs.org/api/sfc-script-setup.html#sfc-script-setup
import HelloWorld from './components/HelloWorld.vue'
import Home from '@/views/Home.vue'
import About from '@/views/About.vue'
import Btn from '@/components/Btn.vue'
export default {
components: {
Home,
About,
Btn
},
data() {
return{
}
},
methods: {
},
computed: {
}
}
</script>
<template>
<div>
<Home></Home>
<About></About>
<Btn></Btn>
</div>
</template>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
getters
getters相当于组件中的computed,getters是全局的,computed是组件内部的
修改index.js
// 在store(仓库)下的index.js这份文件,就是用来做状态管理的
// import Vuex from 'vuex';
import { createStore } from 'vuex';
export default createStore({
// state相当于组件中的data,专门用来存放全局的数据
state: {
num: 0
},
// getters相当于组件中的computed,getters是全局的,computed是组件内部的
getters: {
getNum(state) {
return state.num
}
},
//
mutations: {
increment (state) {
state.num++
}
},
})
修改About.vue
<template>
<div>
<h2>About 页面的 数字: {{ $store.getters.getNum }}</h2>
</div>
</template>
<script>
export default {
computed: {
num() {
return this.$store.state.num
}
}
}
</script>
<style>
</style>
mutations
mutations相当于组件中的methods,但是它不能使用异步方法(定时器、axios)
修改index.js
// 在store(仓库)下的index.js这份文件,就是用来做状态管理的
// import Vuex from 'vuex';
import { createStore } from 'vuex';
export default createStore({
// state相当于组件中的data,专门用来存放全局的数据
state: {
num: 0
},
// getters相当于组件中的computed,getters是全局的,computed是组件内部的
getters: {
getNum(state) {
return state.num
}
},
//mutations相当于组件中的methods,但是它不能使用异步方法(定时器、axios)
mutations: {
increment (state, payload) {
state.num+=payload ? payload : 1
}
},
})
修改Btn.vue
<template>
<div>
<button @click="changeNum(n)">点击加1</button>
<br>
<input v-model.number="n">
{{ $store.state.num }}
</div>
</template>
<script>
export default {
data() {
return{
n: 2
}
},
methods: {
// 调用store中的mutations里的increment方法
// 传参的话,使用payload
changeNum(n) {
console.log(n)
this.$store.commit('increment',n)
}
}
}
</script>
<style>
</style>
actions
actions专门用来处理异步,实际修改状态值的,依然是mutations
修改index.js
// 在store(仓库)下的index.js这份文件,就是用来做状态管理的
// import Vuex from 'vuex';
import { createStore } from 'vuex';
export default createStore({
// state相当于组件中的data,专门用来存放全局的数据
state: {
num: 0
},
// getters相当于组件中的computed,getters是全局的,computed是组件内部的
getters: {
getNum(state) {
return state.num
}
},
//mutations相当于组件中的methods,但是它不能使用异步方法(定时器、axios)
mutations: {
increase (state, payload) {
state.num += payload ? payload : 1
},
clear (state) {
state.num = 0
},
decrease (state, payload) {
if (state.num === 0) {
state.num = 0
} else {
state.num -= payload ? payload : 1
}
}
},
// actions专门用来处理异步,实际修改状态值的,依然是mutations
actions: {
decreaseAync (context, num) {
context.commit('decrease', num)
}
}
})
修改Btn.vue
<template>
<div>
<button @click="changeNum(n)">点击加1</button>
<button @click="subNum(n)">点击减1</button>
<button @click="clearNum">清空</button>
<br>
<input v-model.number="n">
</div>
</template>
<script>
export default {
data() {
return{
n: 1
}
},
methods: {
// 调用store中的mutations里的increment方法
// 传参的话,使用payload
changeNum(n) {
this.$store.commit('increase', n)
},
clearNum() {
this.$store.commit('clear')
},
subNum(n) {
this.$store.dispatch('decreaseAync', n)
}
}
}
</script>
<style>
</style>
Vben Admin
官方文档
D2Admin
API封装
/src/api
axios实例
service.js
自定义API
modules目录
sys.user.api.js
// import { find, assign } from 'lodash'
// const users = [
// { username: 'admin', password: 'admin', uuid: 'admin-uuid', name: 'Admin' },
// { username: 'editor', password: 'editor', uuid: 'editor-uuid', name: 'Editor' },
// { username: 'user1', password: 'user1', uuid: 'user1-uuid', name: 'User1' }
// ]
// import Qs from 'qs'
const baseURL = '/admin'
export default ({ service, request, serviceForMock, requestForMock, mock, faker, tools }) => ({
/**
* @description 登录
* @param {Object} data 登录携带的信息
*/
SYS_USER_LOGIN (data = {}) {
// 模拟数据
// mock
// .onAny('/login')
// .reply(config => {
// const user = find(users, tools.parse(config.data))
// return user
// ? tools.responseSuccess(assign({}, user, { token: faker.random.uuid() }))
// : tools.responseError({}, '账号或密码不正确')
// })
// 接口请求
return request({
url: baseURL + '/login/login',
method: 'post',
data: data
// data: Qs.stringify(data),
// headers: {
// 'Content-Type': 'application/x-www-form-urlencoded'
// }
})
},
FIND_USER_LIST (data = {}) {
return request({
url: baseURL + '/user/getAll',
method: 'post',
data: data
})
},
REFRESH_MSG () {
return request({
url: baseURL + '/user/refreshmsg',
method: 'get'
})
},
ADD_USER (data = {}) {
return request({
url: baseURL + '/user/add',
method: 'post',
data: data
})
},
UPDATE_USER (data = {}) {
return request({
url: baseURL + '/user/update',
method: 'put',
data: data
})
},
DELETE_USER_BY_ID (data = {}) {
return request({
url: baseURL + '/user/delete',
method: 'delete',
data: data
})
}
})
sys.menu.api.js
const baseURL = '/admin'
export default ({ request }) => ({
MENU_CURRENT (data = {}) {
return request({
url: baseURL + '/menu/get/current/menutree',
method: 'get'
})
},
ROUTER_CURRENT (data = {}) {
return request({
url: baseURL + '/menu/get/current/vuerouter',
method: 'get'
})
}
})
登录逻辑
登录页面
/src/views/system/login/page.vue
page.vue
<script>
methods: {
// 通过Vuex 展开action 分发login
...mapActions('d2admin/account', [
'login'
]),
// 提交登录信息
submit () {
this.$refs.loginForm.validate((valid) => {
if (valid) {
// 登录
// 注意 这里的演示没有传验证码
// 具体需要传递的数据请自行修改代码
// 调用action
this.login({
username: this.formLogin.username,
password: this.formLogin.password
})
.then(() => {
// 重定向对象不存在则返回顶层路径
this.$router.replace(this.$route.query.redirect || '/')
})
} else {
// 登录表单校验失败
this.$message.error('表单校验失败,请检查')
}
})
}
</script>
/src/store/modules/d2admin/modules/account.js
account.js
actions: {
/**
* @description 登录
* @param {Object} context
* @param {Object} payload username {String} 用户账号
* @param {Object} payload password {String} 密码
* @param {Object} payload route {Object} 登录成功后定向的路由对象 任何 vue-router 支持的格式
*/
async login ({ dispatch }, {
username = '',
password = '',
to = '/'
} = {}) {
// 这里axios请求
const res = await api.SYS_USER_LOGIN({ username, password })
// 设置 cookie 一定要存 uuid 和 token 两个 cookie
// 整个系统依赖这两个数据进行校验和存储
// uuid 是用户身份唯一标识 用户注册的时候确定 并且不可改变 不可重复
// token 代表用户当前登录状态 建议在网络请求中携带 token
// 如有必要 token 需要定时更新,默认保存一天
util.cookies.set('uuid', res.uuid)
util.cookies.set('token', res.token)
// 设置 vuex 用户信息
await dispatch('d2admin/user/set', { name: res.name }, { root: true })
// 用户登录后从持久化数据加载一系列的设置
await dispatch('load')
// 此处执行动态菜单 动态路由
await dispatch('updateCache', { to: to })
},
}
动态菜单
修改main.js入口文件
new Vue({
router,
store,
i18n,
render: h => h(App),
created () {
// 处理路由 得到每一级的路由设置
this.$store.commit('d2admin/page/init', frameInRoutes)
// 设置顶栏菜单
// this.$store.commit('d2admin/menu/headerSet', menuHeader)
// 设置侧边栏菜单
// this.$store.commit('d2admin/menu/asideSet', menuAside)
// 对于已登录的做菜单,搜索数据处理
this.$store.dispatch('d2admin/menu/get')
// 初始化菜单搜索功能 修改搜索数据根据侧边栏还是头部栏
// this.$store.commit('d2admin/search/init', menuAside)
},
注释掉以下 mutation
// 设置顶栏菜单
// this.$store.commit('d2admin/menu/headerSet', menuHeader)
// 设置侧边栏菜单
// this.$store.commit('d2admin/menu/asideSet', menuAside)
所有逻辑在Vuex中完成
到 /src/store/modules/d2admin/modules/menu.js
menu.js
// 设置文件
import setting from '@/setting.js'
import api from '@/api'
import { uniqueId } from 'lodash'
// 这是从/src/menu/index.js拿到的方法 负责给菜单空的path加上 d2-menu-empty- #随机数字 需要引入lodash uniqueId
function supplementPath (menu) {
return menu.map(e => ({
...e,
path: e.path || uniqueId('d2-menu-empty-'),
...e.children ? {
children: supplementPath(e.children)
} : {}
}))
}
export default {
namespaced: true,
state: {
// 顶栏菜单
header: [],
// 侧栏菜单
aside: [],
// 侧边栏收缩
asideCollapse: setting.menu.asideCollapse,
// 侧边栏折叠动画
asideTransition: setting.menu.asideTransition
},
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',
value: state.asideCollapse,
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',
value: state.asideCollapse,
user: true
}, { root: true })
},
// 以下为生成菜单数据的 action
/**
* 设置菜单
* @param {*} param0
* @param {*} aside
*/
async set ({ state, dispatch }, aside) {
aside = supplementPath(Array.from(await api.MENU_CURRENT()))
state.aside = aside
console.log('---set-------')
// 持久化
await dispatch('d2admin/db/set', {
dbName: 'sys',
path: 'menu.aside',
value: aside,
user: true
}, { root: true })
// 搜索
await dispatch('d2admin/search/init', aside, { root: true })
},
// 这个是页面刷新用到的
async get ({ state, dispatch, commit }) {
state.aside = await dispatch('d2admin/db/get', {
dbName: 'sys',
path: 'menu.aside',
defaultValue: [],
user: true
}, { root: true })
commit('asideSet', state.aside)
// 搜索
await dispatch('d2admin/search/init', state.aside, { 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',
value: state.asideTransition,
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',
value: state.asideTransition,
user: true
}, { root: true })
},
/**
* 持久化数据加载侧边栏设置
* @param {Object} context
*/
async asideLoad ({ state, dispatch }) {
// store 赋值
const menu = 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
}
},
mutations: {
/**
* @description 设置顶栏菜单
* @param {Object} state state
* @param {Array} menu menu setting
*/
headerSet (state, menu) {
// store 赋值
state.header = menu
},
/**
* @description 设置侧边栏菜单
* @param {Object} state state
* @param {Array} menu menu setting
*/
asideSet (state, menu) {
// store 赋值
state.aside = menu
}
}
}
到 /src/store/modules/d2admin/modules/account.js
account.js
新增一个action updateCache
updateCache ({ dispatch }, { to = '/' }) {
return new Promise((resolve, reject) => {
// 设置菜单
dispatch('d2admin/menu/set', {}, { root: true })
// 设置路由
api.ROUTER_CURRENT().then(result => {
dispatch('d2admin/router/load', { to: to, focus: true, data: result }, { root: true })
})
resolve()
})
}
api请求
/src/api/modules/sys.menu.api.js
sys.menu.api.js
const baseURL = '/admin'
export default ({ request }) => ({
// 菜单请求
MENU_CURRENT (data = {}) {
return request({
url: baseURL + '/menu/get/current/menutree',
method: 'get'
})
},
// 路由请求
ROUTER_CURRENT (data = {}) {
return request({
url: baseURL + '/menu/get/current/vuerouter',
method: 'get'
})
}
})
响应报文
{
"code": 0,
"msg": "请求成功",
"data": [
{
"id": 1,
"title": "信评中心",
"enname": "crManager",
"parentId": -1,
"icon": "folder-o",
"sort": 1,
"isEnabled": 1,
"children": [
{
"id": 2,
"title": "信评工作台",
"enname": "crWorkbench",
"parentId": 1,
"icon": "folder-o",
"sort": 2,
"isEnabled": 1,
"children": [
{
"id": 3,
"title": "信用评级待办",
"parentId": 2,
"icon": "folder-o",
"sort": 3,
"isEnabled": 1
}
]
},
{
"id": 4,
"title": "信用评级启动",
"parentId": 1,
"icon": "folder-o",
"isEnabled": 1,
"children": [
{
"id": 5,
"title": "个人评级",
"enname": "cr_person_launch",
"parentId": 4,
"path": "/cr_person_launch",
"component": "cr/cr_launch/cr_person_launch/cr_person_launch",
"icon": "folder-o",
"isEnabled": 1
},
{
"id": 6,
"title": "企业评级",
"enname": "cr_business_launch",
"parentId": 4,
"path": "/cr_business_launch",
"component": "cr/cr_launch/cr_business_launch/cr_business_launch",
"icon": "folder-o",
"isEnabled": 1
}
]
},
{
"id": 7,
"title": "信用评级查询",
"parentId": 1,
"icon": "folder-o",
"isEnabled": 1
},
{
"id": 8,
"title": "评级模板管理",
"parentId": 1,
"icon": "folder-o",
"isEnabled": 1
}
]
},
{
"id": 9,
"title": "系统管理",
"parentId": -1,
"icon": "folder-o",
"isEnabled": 1,
"children": [
{
"id": 10,
"title": "用户管理",
"enname": "usertable",
"parentId": 9,
"path": "/usertable",
"component": "user/usertable",
"icon": "folder-o",
"isEnabled": 1
},
{
"id": 11,
"title": "菜单管理",
"enname": "menu",
"parentId": 9,
"path": "/menu",
"component": "menu/menu",
"isEnabled": 1
},
{
"id": 16,
"title": "权限管理",
"enname": "role",
"parentId": 9,
"path": "/role",
"component": "role/role",
"isEnabled": 1
}
]
},
{
"id": 12,
"title": "演示页面",
"parentId": -1,
"isEnabled": 1,
"children": [
{
"id": 13,
"title": "页面 1",
"enname": "page1",
"parentId": 12,
"path": "/page1",
"component": "demo/page1",
"isEnabled": 1
},
{
"id": 14,
"title": "页面 2",
"enname": "page2",
"parentId": 12,
"path": "/page2",
"component": "demo/page2",
"isEnabled": 1
},
{
"id": 15,
"title": "页面 3",
"enname": "page3",
"parentId": 12,
"path": "/page3",
"component": "demo/page3",
"isEnabled": 1
}
]
}
],
"type": "success"
}