@ -1,4 +1,4 @@ |
|||||||
import request from "@/config/request" |
import request from "@/api/request" |
||||||
import {isEmpty} from "@/util" |
import {isEmpty} from "@/util" |
||||||
|
|
||||||
export const baseUrl = '/account' |
export const baseUrl = '/account' |
||||||
@ -1,4 +1,4 @@ |
|||||||
import request from "@/config/request" |
import request from "@/api/request" |
||||||
|
|
||||||
export const baseUrl = '/record' |
export const baseUrl = '/record' |
||||||
|
|
||||||
@ -1,4 +1,4 @@ |
|||||||
import request from "@/config/request" |
import request from "@/api/request" |
||||||
|
|
||||||
export const baseUrl = `/statistic` |
export const baseUrl = `/statistic` |
||||||
|
|
||||||
@ -1,8 +1,20 @@ |
|||||||
import request from "@/config/request" |
import request from "@/api/request" |
||||||
import BASE from './baseUrl' |
import BASE from './baseUrl' |
||||||
|
|
||||||
export const baseUrl = `${BASE}/resource` |
export const baseUrl = `${BASE}/resource` |
||||||
|
|
||||||
export function getAllResources() { |
export function getAll() { |
||||||
return request.get(`${baseUrl}/getAll`).then(({data}) => data.data) |
return request.get(`${baseUrl}/getAll`).then(({data}) => data.data) |
||||||
} |
} |
||||||
|
|
||||||
|
export function add(data) { |
||||||
|
return request.post(`${baseUrl}/add`, data).then(({data}) => data) |
||||||
|
} |
||||||
|
|
||||||
|
export function update(data) { |
||||||
|
return request.post(`${baseUrl}/update`, data).then(({data}) => data) |
||||||
|
} |
||||||
|
|
||||||
|
export function del(id) { |
||||||
|
return request.get(`${baseUrl}/del?id=${id}`).then(({data}) => data) |
||||||
|
} |
||||||
|
|||||||
@ -1,24 +1,24 @@ |
|||||||
import request from "@/config/request" |
import request from "@/api/request" |
||||||
import BASE from './baseUrl' |
import BASE from './baseUrl' |
||||||
|
|
||||||
export const baseUrl = `${BASE}/role` |
export const baseUrl = `${BASE}/role` |
||||||
|
|
||||||
export function searchRoles(data) { |
export function search(data) { |
||||||
return request.post(`${baseUrl}/search`, data).then(({data}) => data.data) |
return request.post(`${baseUrl}/search`, data).then(({data}) => data.data) |
||||||
} |
} |
||||||
|
|
||||||
export function getRoles() { |
export function get() { |
||||||
return request.get(`${baseUrl}/get`).then(({data}) => data.data) |
return request.get(`${baseUrl}/get`).then(({data}) => data.data) |
||||||
} |
} |
||||||
|
|
||||||
export function addRole(data) { |
export function add(data) { |
||||||
return request.post(`${baseUrl}/add`, data).then(({data}) => data) |
return request.post(`${baseUrl}/add`, data).then(({data}) => data) |
||||||
} |
} |
||||||
|
|
||||||
export function updateRole(data) { |
export function update(data) { |
||||||
return request.post(`${baseUrl}/update`, data).then(({data}) => data) |
return request.post(`${baseUrl}/update`, data).then(({data}) => data) |
||||||
} |
} |
||||||
|
|
||||||
export function delRole(data) { |
export function del(data) { |
||||||
return request.post(`${baseUrl}/del`, data).then(({data}) => data) |
return request.post(`${baseUrl}/del`, data).then(({data}) => data) |
||||||
} |
} |
||||||
|
|||||||
@ -1,50 +0,0 @@ |
|||||||
<script type="text/jsx"> |
|
||||||
import {isExternal} from '@/util/validate' |
|
||||||
|
|
||||||
export default { |
|
||||||
name: 'SvgIcon', |
|
||||||
|
|
||||||
functional: true, |
|
||||||
|
|
||||||
props: { |
|
||||||
icon: String, |
|
||||||
className: String |
|
||||||
}, |
|
||||||
|
|
||||||
render(h, context) { |
|
||||||
const {listeners} = context |
|
||||||
const {icon, className} = context.props |
|
||||||
const c = 'svg-icon ' + (className || '') |
|
||||||
if (isExternal(icon)) { |
|
||||||
const style = { |
|
||||||
mask: `url(${this.icon}) no-repeat 50% 50%`, |
|
||||||
'-webkit-mask': `url(${this.icon}) no-repeat 50% 50%` |
|
||||||
} |
|
||||||
return <div {...{on: listeners}} class={'svg-external-icon ' + c} style={style}/> |
|
||||||
} |
|
||||||
else { |
|
||||||
const iconName = `#icon-${icon}` |
|
||||||
return ( |
|
||||||
<svg {...{on: listeners}} class={c} aria-hidden="true"> |
|
||||||
<use href={iconName}/> |
|
||||||
</svg> |
|
||||||
) |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
</script> |
|
||||||
|
|
||||||
<style> |
|
||||||
.svg-icon { |
|
||||||
width: 1em; |
|
||||||
height: 1em; |
|
||||||
fill: currentColor; |
|
||||||
overflow: hidden; |
|
||||||
} |
|
||||||
|
|
||||||
.svg-external-icon { |
|
||||||
background-color: currentColor; |
|
||||||
mask-size: cover !important; |
|
||||||
display: inline-block; |
|
||||||
} |
|
||||||
</style> |
|
||||||
@ -0,0 +1,34 @@ |
|||||||
|
<script type="text/jsx"> |
||||||
|
|
||||||
|
export default { |
||||||
|
name: 'VIcon', |
||||||
|
|
||||||
|
functional: true, |
||||||
|
|
||||||
|
props: {icon: String}, |
||||||
|
|
||||||
|
render(h, context) { |
||||||
|
const {data, props: {icon}} = context |
||||||
|
const svgPrefix = 'svg-' |
||||||
|
|
||||||
|
if (icon.startsWith(svgPrefix)) { |
||||||
|
return ( |
||||||
|
<svg class="icon" aria-hidden="true" {...data}> |
||||||
|
<use href={`#icon-${icon.replace(svgPrefix, '')}`}/> |
||||||
|
</svg> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
return <i class={icon} {...data}/> |
||||||
|
} |
||||||
|
} |
||||||
|
</script> |
||||||
|
|
||||||
|
<style> |
||||||
|
.icon { |
||||||
|
width: 1em; |
||||||
|
height: 1em; |
||||||
|
fill: currentColor; |
||||||
|
overflow: hidden; |
||||||
|
} |
||||||
|
</style> |
||||||
@ -0,0 +1,46 @@ |
|||||||
|
<template> |
||||||
|
<textarea/> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
import CodeMirror from 'codemirror' |
||||||
|
import 'codemirror/lib/codemirror.css' |
||||||
|
import 'codemirror/theme/rubyblue.css' |
||||||
|
import 'codemirror/mode/javascript/javascript' |
||||||
|
import {isEmpty} from "@/util" |
||||||
|
|
||||||
|
export default { |
||||||
|
name: "JsonEditor", |
||||||
|
|
||||||
|
props: ['value'], |
||||||
|
|
||||||
|
watch: { |
||||||
|
value(value) { |
||||||
|
const editorValue = this.jsonEditor.getValue() |
||||||
|
if (value !== editorValue) { |
||||||
|
this.jsonEditor.setValue(this.value) |
||||||
|
} |
||||||
|
} |
||||||
|
}, |
||||||
|
|
||||||
|
mounted() { |
||||||
|
this.jsonEditor = CodeMirror.fromTextArea( |
||||||
|
this.$el, |
||||||
|
{ |
||||||
|
mode: 'application/json', |
||||||
|
theme: 'rubyblue' |
||||||
|
} |
||||||
|
) |
||||||
|
|
||||||
|
!isEmpty(this.value) && this.jsonEditor.setValue(this.value) |
||||||
|
this.jsonEditor.on('change', cm => { |
||||||
|
this.$emit('input', cm.getValue()) |
||||||
|
}) |
||||||
|
}, |
||||||
|
|
||||||
|
beforeDestroy() { |
||||||
|
const element = this.jsonEditor.doc.cm.getWrapperElement() |
||||||
|
element && element.remove && element.remove() |
||||||
|
} |
||||||
|
} |
||||||
|
</script> |
||||||
|
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 379 B After Width: | Height: | Size: 379 B |
|
Before Width: | Height: | Size: 351 B After Width: | Height: | Size: 351 B |
|
Before Width: | Height: | Size: 284 B After Width: | Height: | Size: 284 B |
|
Before Width: | Height: | Size: 305 B After Width: | Height: | Size: 305 B |
|
Before Width: | Height: | Size: 490 B After Width: | Height: | Size: 490 B |
|
Before Width: | Height: | Size: 961 B After Width: | Height: | Size: 961 B |
@ -1,13 +1,13 @@ |
|||||||
import BottomTip from './BottomTip' |
import BottomTip from './BottomTip' |
||||||
import Guide from './Guide' |
import Guide from './Guide' |
||||||
import ImageViewer from './ImageViewer' |
import ImageViewer from './ImageViewer' |
||||||
import PuzzleVerify from './PuzzleVerify' |
import Verify from './Verify' |
||||||
import Signature from './SignautreBoard' |
import Signature from './SignautreBoard' |
||||||
|
|
||||||
export default function (Vue) { |
export default function (Vue) { |
||||||
Vue.prototype.$bottomTip = BottomTip |
Vue.prototype.$bottomTip = BottomTip |
||||||
Vue.prototype.$guide = Guide |
Vue.prototype.$guide = Guide |
||||||
Vue.prototype.$image = ImageViewer |
Vue.prototype.$image = ImageViewer |
||||||
Vue.prototype.$puzzleVerify = PuzzleVerify |
Vue.prototype.$verify = Verify |
||||||
Vue.prototype.$signature = Signature |
Vue.prototype.$signature = Signature |
||||||
} |
} |
||||||
|
|||||||
@ -0,0 +1,34 @@ |
|||||||
|
/* |
||||||
|
* 树形控件页通用混入 |
||||||
|
* */ |
||||||
|
|
||||||
|
const mixin = { |
||||||
|
data() { |
||||||
|
return { |
||||||
|
curNode: null |
||||||
|
} |
||||||
|
}, |
||||||
|
|
||||||
|
watch: { |
||||||
|
curNode(v) { |
||||||
|
const ref = this.$refs.tree |
||||||
|
!v && ref && ref.setCurrentKey() |
||||||
|
} |
||||||
|
}, |
||||||
|
|
||||||
|
methods: { |
||||||
|
nodeClick(data, node, ref) { |
||||||
|
if (this.curNode === node) { |
||||||
|
this.$refs.tree.setCurrentKey() |
||||||
|
this.curNode = null |
||||||
|
} |
||||||
|
else this.curNode = node |
||||||
|
|
||||||
|
if (this.afterNodeClick) { |
||||||
|
this.afterNodeClick(data, node, ref, !this.curNode) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
export default mixin |
||||||
@ -0,0 +1,13 @@ |
|||||||
|
export const nodeType = [ |
||||||
|
{label: '聚合菜单', value: 1, icon: 'el-icon-folder'}, |
||||||
|
{label: '页面菜单', value: 2, icon: 'el-icon-document'}, |
||||||
|
{label: '数据接口', value: 3, icon: 'el-icon-open'}, |
||||||
|
] |
||||||
|
|
||||||
|
export function getNodeInfo({data: {type}} = {}) { |
||||||
|
return nodeType.find(i => i.value === type) |
||||||
|
} |
||||||
|
|
||||||
|
export function getNodeTitle({data: {type, name, meta}}) { |
||||||
|
return type === 3 ? name : meta.title |
||||||
|
} |
||||||
@ -0,0 +1,358 @@ |
|||||||
|
<template> |
||||||
|
<el-card> |
||||||
|
<el-row class="button-group"> |
||||||
|
<template v-if="canAdd"> |
||||||
|
<el-button icon="el-icon-plus" size="small" type="primary" @click="addRoot">添加根节点</el-button> |
||||||
|
<el-button icon="el-icon-plus" size="small" type="primary" @click="addChild">添加子节点</el-button> |
||||||
|
</template> |
||||||
|
<el-button v-if="canDel" icon="el-icon-delete" size="small" type="danger" @click="del">删 除</el-button> |
||||||
|
<el-dropdown placement="bottom" size="small" @command="more"> |
||||||
|
<el-button plain size="small"> |
||||||
|
更多操作 |
||||||
|
<i class="el-icon-arrow-down el-icon--right"/> |
||||||
|
</el-button> |
||||||
|
<el-dropdown-menu slot="dropdown"> |
||||||
|
<el-dropdown-item :command="{action:'expand',level:0}">展开全部</el-dropdown-item> |
||||||
|
<el-dropdown-item :command="{action:'collapse',level:0}">收起全部</el-dropdown-item> |
||||||
|
<el-dropdown-item :command="{action:'expand',level:1}">仅展开一级</el-dropdown-item> |
||||||
|
</el-dropdown-menu> |
||||||
|
</el-dropdown> |
||||||
|
</el-row> |
||||||
|
|
||||||
|
<el-row :gutter="100" style="margin-top: 20px;"> |
||||||
|
<el-col :xs="24" :sm="11" :md="9" :lg="8" :xl="6"> |
||||||
|
<el-alert show-icon :closable="false"> |
||||||
|
<template v-slot:title> |
||||||
|
当前选择编辑: |
||||||
|
<el-tag v-if="curNode" size="mini" closable @close="() => curNode = null"> |
||||||
|
{{ getNodeTitle(curNode) }} |
||||||
|
</el-tag> |
||||||
|
</template> |
||||||
|
</el-alert> |
||||||
|
|
||||||
|
<el-input |
||||||
|
v-model="search" |
||||||
|
placeholder="输入菜单名搜索" |
||||||
|
suffix-icon="el-icon-search" |
||||||
|
size="small" |
||||||
|
style="margin-top: 10px" |
||||||
|
@input="v => $refs.tree.filter(v)" |
||||||
|
/> |
||||||
|
|
||||||
|
<div style="max-height: 660px;overflow: auto;margin-top: 10px"> |
||||||
|
<el-tree |
||||||
|
ref="tree" |
||||||
|
:data="menus" |
||||||
|
node-key="id" |
||||||
|
highlight-current |
||||||
|
accordion |
||||||
|
:expand-on-click-node="false" |
||||||
|
:filter-node-method="filterNodeMethod" |
||||||
|
@node-click="nodeClick" |
||||||
|
> |
||||||
|
<span slot-scope="{node}" class="el-tree-node__label"> |
||||||
|
<v-icon :icon="getNodeInfo(node).icon"/> |
||||||
|
{{ getNodeTitle(node) }} |
||||||
|
</span> |
||||||
|
</el-tree> |
||||||
|
</div> |
||||||
|
</el-col> |
||||||
|
|
||||||
|
<el-col :xs="24" :sm="13" :md="15" :lg="13" :xl="11"> |
||||||
|
<abstract-form v-if="showForm" :model="form" :rules="rules"> |
||||||
|
<el-form-item label="类型"> |
||||||
|
<el-select |
||||||
|
v-if="showTypeSelector" |
||||||
|
:value="form.type" |
||||||
|
placeholder="请选择类型" |
||||||
|
@change="typeChange" |
||||||
|
> |
||||||
|
<v-icon slot="prefix" :icon="getNodeInfo({data:form}).icon"/> |
||||||
|
<el-option |
||||||
|
v-for="{label,value,icon} in nodeType" |
||||||
|
:key="value" |
||||||
|
:label="label" |
||||||
|
:value="value" |
||||||
|
:disabled="value === 3" |
||||||
|
> |
||||||
|
<v-icon :icon="icon"/> |
||||||
|
{{ label }} |
||||||
|
</el-option> |
||||||
|
</el-select> |
||||||
|
|
||||||
|
<template v-else> |
||||||
|
<v-icon :icon="getNodeInfo({data:form}).icon"/> |
||||||
|
{{ getNodeInfo({data: form}).label }} |
||||||
|
</template> |
||||||
|
</el-form-item> |
||||||
|
|
||||||
|
<el-form-item v-if="form.pid" label="上级菜单"> |
||||||
|
<v-icon :icon="getParentNodeInfo().icon"/> |
||||||
|
{{ getParentNodeInfo().title }} |
||||||
|
</el-form-item> |
||||||
|
|
||||||
|
<el-form-item label="名称" prop="title"> |
||||||
|
<el-input v-if="form.type === 3" v-model="form.name" maxlength="10"/> |
||||||
|
<template v-else>{{ form.meta.title }}</template> |
||||||
|
</el-form-item> |
||||||
|
|
||||||
|
<el-form-item label="路径" prop="path"> |
||||||
|
<el-input v-model="form.path" maxlength="100"/> |
||||||
|
</el-form-item> |
||||||
|
|
||||||
|
<!--菜单独有配置项--> |
||||||
|
<template v-if="form.type !== 3"> |
||||||
|
<!--叶子菜单独有配置项--> |
||||||
|
<template v-if="form.type === 2"> |
||||||
|
<el-form-item label="路由名称" prop="name"> |
||||||
|
<el-input v-model="form.name" maxlength="50"/> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item label="菜单组件" prop="component"> |
||||||
|
<el-input v-model="form.component" maxlength="50"/> |
||||||
|
</el-form-item> |
||||||
|
</template> |
||||||
|
|
||||||
|
<el-form-item label="meta" prop="meta"> |
||||||
|
<json-editor v-model="form.metaStr" @input="metaChange"/> |
||||||
|
</el-form-item> |
||||||
|
</template> |
||||||
|
|
||||||
|
<el-form-item label="admin独有"> |
||||||
|
<el-switch v-model="form.admin" active-text="是" inactive-text="否"/> |
||||||
|
</el-form-item> |
||||||
|
|
||||||
|
<el-form-item label="是否启用"> |
||||||
|
<el-switch v-model="form.enable" active-text="是" inactive-text="否"/> |
||||||
|
</el-form-item> |
||||||
|
|
||||||
|
<el-form-item v-if="showSaveBtn"> |
||||||
|
<el-button |
||||||
|
:loading="loading" |
||||||
|
icon="el-icon-edit-outline" |
||||||
|
size="small" |
||||||
|
type="primary" |
||||||
|
@click="save" |
||||||
|
> |
||||||
|
保 存 |
||||||
|
</el-button> |
||||||
|
</el-form-item> |
||||||
|
</abstract-form> |
||||||
|
</el-col> |
||||||
|
</el-row> |
||||||
|
</el-card> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
import treePageMixin from '@/mixin/treePageMixin' |
||||||
|
import AbstractForm from "@/component/AbstractForm" |
||||||
|
import JsonEditor from "@/component/editor/JsonEditor" |
||||||
|
import {baseUrl, add, update, del} from '@/api/system/resource' |
||||||
|
import {isEmpty, mergeObj, resetObj} from "@/util" |
||||||
|
import {elSuccess, elError, elConfirm} from "@/util/message" |
||||||
|
import {elTreeControl} from "@/util/tree" |
||||||
|
import {auth} from "@/util/auth" |
||||||
|
import {nodeType, getNodeInfo, getNodeTitle} from "./common" |
||||||
|
|
||||||
|
export default { |
||||||
|
name: "menuManagement", |
||||||
|
|
||||||
|
mixins: [treePageMixin], |
||||||
|
|
||||||
|
components: {AbstractForm, JsonEditor}, |
||||||
|
|
||||||
|
data() { |
||||||
|
const validateTitle = (r, v, c) => { |
||||||
|
const value = getNodeTitle({data: this.form}) |
||||||
|
c(isEmpty(value) ? '名称不能为空' : undefined) |
||||||
|
} |
||||||
|
return { |
||||||
|
loading: false, |
||||||
|
search: null, |
||||||
|
type: 'add',// add or edit |
||||||
|
nodeType, |
||||||
|
form: { |
||||||
|
id: null, |
||||||
|
pid: null, |
||||||
|
type: 0, |
||||||
|
name: null, |
||||||
|
path: null, |
||||||
|
component: null, |
||||||
|
meta: { |
||||||
|
title: null, |
||||||
|
dynamicTitle: null, |
||||||
|
hidden: false, |
||||||
|
alwaysShow: false, |
||||||
|
sort: null, |
||||||
|
icon: null, |
||||||
|
affix: false, |
||||||
|
noCache: false, |
||||||
|
activeMenu: null, |
||||||
|
noAuth: false, |
||||||
|
iframe: null, |
||||||
|
usePathKey: false, |
||||||
|
useFullPathKey: false, |
||||||
|
commonModule: null |
||||||
|
}, |
||||||
|
metaStr: null, |
||||||
|
admin: false, |
||||||
|
enable: true |
||||||
|
}, |
||||||
|
rules: { |
||||||
|
title: [{validator: validateTitle, trigger: 'change'}], |
||||||
|
path: [{required: true, message: '路径不能为空', trigger: 'change'}], |
||||||
|
} |
||||||
|
} |
||||||
|
}, |
||||||
|
|
||||||
|
computed: { |
||||||
|
canAdd() { |
||||||
|
return auth(`${baseUrl}/add`) |
||||||
|
}, |
||||||
|
canUpdate() { |
||||||
|
return auth(`${baseUrl}/update`) |
||||||
|
}, |
||||||
|
canDel() { |
||||||
|
return auth(`${baseUrl}/del`) |
||||||
|
}, |
||||||
|
|
||||||
|
menus() { |
||||||
|
return this.$store.state.resource.resourceTree |
||||||
|
}, |
||||||
|
showForm() { |
||||||
|
return this.type === 'add' && this.form.pid === 0 || this.curNode |
||||||
|
}, |
||||||
|
showTypeSelector() { |
||||||
|
const isRoot = this.form.pid === 0 |
||||||
|
//1.非数据接口 |
||||||
|
const noApiNode = this.form.type !== 3 |
||||||
|
//2.其下无子节点 |
||||||
|
const noChild = this.type === 'add' && isRoot |
||||||
|
|| this.type === 'edit' && this.curNode.childNodes.length <= 0 |
||||||
|
//3.不是初始节点 |
||||||
|
const noInitialNode = this.form.path !== '/' || isRoot |
||||||
|
//4.父节点只能为聚合菜单 |
||||||
|
const parentIsFolderMenu = |
||||||
|
isRoot |
||||||
|
? true |
||||||
|
: this.type === 'add' && this.curNode.data.type === 1 |
||||||
|
|| this.type === 'edit' && this.curNode.parent.data.type === 1 |
||||||
|
return noApiNode && noChild && noInitialNode && parentIsFolderMenu |
||||||
|
}, |
||||||
|
showSaveBtn() { |
||||||
|
return this.type === 'add' && this.canAdd || this.type === 'edit' && this.canUpdate |
||||||
|
} |
||||||
|
}, |
||||||
|
|
||||||
|
methods: { |
||||||
|
getNodeInfo, |
||||||
|
getNodeTitle, |
||||||
|
getParentNodeInfo() { |
||||||
|
const node = this.type === 'add' ? this.curNode : this.curNode.parent |
||||||
|
const {icon} = getNodeInfo(node) |
||||||
|
return {icon, title: getNodeTitle(node)} |
||||||
|
}, |
||||||
|
filterNodeMethod(value, data) { |
||||||
|
if (isEmpty(value)) return true |
||||||
|
return getNodeTitle({data}).includes(value) |
||||||
|
}, |
||||||
|
afterNodeClick(data, node, ref, clear) { |
||||||
|
if (clear) return this.clearForm() |
||||||
|
this.type = 'edit' |
||||||
|
this.$refs.form && this.$refs.form.clearValidate() |
||||||
|
mergeObj(this.form, data) |
||||||
|
if (data.meta) { |
||||||
|
this.form.metaStr = JSON.stringify(data.meta, null, 2) |
||||||
|
} |
||||||
|
}, |
||||||
|
//json编辑器值改变时 |
||||||
|
metaChange(v) { |
||||||
|
try { |
||||||
|
v = JSON.parse(v) |
||||||
|
} |
||||||
|
catch (e) { |
||||||
|
return |
||||||
|
} |
||||||
|
resetObj(this.form.meta) |
||||||
|
mergeObj(this.form.meta, v) |
||||||
|
}, |
||||||
|
//表单中菜单类型选择器改变时 |
||||||
|
typeChange(v) { |
||||||
|
//从聚合改为页面菜单时,清空component |
||||||
|
if (v === 2 && this.form.type === 1) { |
||||||
|
this.form.component = null |
||||||
|
} |
||||||
|
this.form.type = v |
||||||
|
}, |
||||||
|
|
||||||
|
addRoot() { |
||||||
|
if (this.loading) return |
||||||
|
this.curNode = null |
||||||
|
this.type = 'add' |
||||||
|
this.clearForm() |
||||||
|
this.form.pid = 0 |
||||||
|
this.form.type = 1 |
||||||
|
}, |
||||||
|
addChild() { |
||||||
|
if (this.loading) return |
||||||
|
if (!this.curNode) return elError('请选择一个节点') |
||||||
|
const {data: {id, type}} = this.curNode |
||||||
|
if (type === 3) return elError('数据接口不能作为父节点') |
||||||
|
this.type = 'add' |
||||||
|
this.clearForm() |
||||||
|
this.form.pid = id |
||||||
|
//如果是叶子菜单,那么只能添加接口 |
||||||
|
this.form.type = type === 2 ? 3 : 1 |
||||||
|
}, |
||||||
|
del() { |
||||||
|
if (this.loading) return |
||||||
|
if (!this.curNode) return elError('请选择要删除的节点') |
||||||
|
elConfirm(`确定删除【${getNodeTitle(this.curNode)}】?`) |
||||||
|
.then(() => { |
||||||
|
this.loading = true |
||||||
|
return del(this.curNode.data.id) |
||||||
|
}) |
||||||
|
.then(() => { |
||||||
|
elSuccess('删除成功') |
||||||
|
this.init() |
||||||
|
}) |
||||||
|
.finally(() => this.loading = false) |
||||||
|
}, |
||||||
|
more({action, level}) { |
||||||
|
if (this.loading) return |
||||||
|
elTreeControl(this.$refs.tree, action, level) |
||||||
|
}, |
||||||
|
|
||||||
|
init() { |
||||||
|
this.curNode = null |
||||||
|
this.clearForm() |
||||||
|
return this.$store.dispatch('resource/init', this.$store.state.user) |
||||||
|
}, |
||||||
|
clearForm() { |
||||||
|
resetObj(this.form) |
||||||
|
this.form.id = null |
||||||
|
this.form.pid = null |
||||||
|
this.form.metaStr = JSON.stringify({title: ''}, null, 2) |
||||||
|
this.form.meta.sort = null |
||||||
|
this.form.enable = true |
||||||
|
}, |
||||||
|
save() { |
||||||
|
if (this.loading) return |
||||||
|
this.$refs.form.validate(v => { |
||||||
|
if (!v) return |
||||||
|
this.loading = true |
||||||
|
const data = this.transformForm() |
||||||
|
const promise = this.type === 'add' ? add(data) : update(data) |
||||||
|
promise |
||||||
|
.then(({data, msg}) => { |
||||||
|
elSuccess(msg) |
||||||
|
return this.init() |
||||||
|
}) |
||||||
|
.finally(() => this.loading = false) |
||||||
|
}) |
||||||
|
}, |
||||||
|
transformForm() { |
||||||
|
return {...this.form, meta: this.form.metaStr, metaStr: undefined} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
</script> |
||||||