角色和用户管理

This commit is contained in:
wuyanwen
2019-12-25 22:12:16 +08:00
parent ceda3a224a
commit 4a3f043166
12 changed files with 518 additions and 288 deletions

1
extend/catcher/Utils.php Normal file
View File

@@ -0,0 +1 @@
<?php

View File

@@ -0,0 +1,44 @@
/**
* 角色管理模块
*
*/
import { axios } from '@/utils/request'
export function getRoleList (parameter) {
return axios({
url: '/roles',
method: 'get',
params: parameter
})
}
export function store (parameter) {
return axios({
url: '/roles',
method: 'post',
data: parameter
})
}
export function read (id) {
return axios({
url: '/roles/' + id,
method: 'get'
})
}
export function update (id, parameter) {
return axios({
url: '/roles/' + id,
method: 'put',
data: parameter
})
}
export function del (id) {
return axios({
url: '/roles/' + id,
method: 'delete'
})
}

View File

@@ -1,51 +1,51 @@
/**
* 用户管理模块
*
*/
import { axios } from '@/utils/request'
export function getUsers (parameter) {
return axios({
url: '/user',
method: 'get',
params: parameter
})
}
export function store (parameter) {
return axios({
url: '/user',
method: 'post',
data: parameter
})
}
export function read (id) {
return axios({
url: '/user/' + id,
method: 'get'
})
}
export function update (id, parameter) {
return axios({
url: '/user/' + id,
method: 'put',
data: parameter
})
}
export function del (id) {
return axios({
url: '/user/' + id,
method: 'delete'
})
}
export function swtichStatus (id) {
return axios({
url: 'user/switch/status/' + id,
method: 'put'
})
}
/**
* 用户管理模块
*
*/
import { axios } from '@/utils/request'
export function getUserList (parameter) {
return axios({
url: '/users',
method: 'get',
params: parameter
})
}
export function store (parameter) {
return axios({
url: '/users',
method: 'post',
data: parameter
})
}
export function read (id) {
return axios({
url: '/users/' + id,
method: 'get'
})
}
export function update (id, parameter) {
return axios({
url: '/users/' + id,
method: 'put',
data: parameter
})
}
export function del (id) {
return axios({
url: '/users/' + id,
method: 'delete'
})
}
export function swtichStatus (id) {
return axios({
url: '/users/switch/status/' + id,
method: 'put'
})
}

View File

@@ -85,8 +85,15 @@ export const asyncRouterMap = [
path: '/permissions/users',
name: 'users',
hideChildrenInMenu: true, // 强制显示 MenuItem 而不是 SubMenu
component: () => import('@/views/permissions/users'),
component: () => import('@/views/permissions/users/users'),
meta: { title: '用户管理', keepAlive: true, permission: [ 'permission' ] }
},
{
path: '/permissions/roles',
name: 'roles',
hideChildrenInMenu: true, // 强制显示 MenuItem 而不是 SubMenu
component: () => import('@/views/permissions/roles/roles'),
meta: { title: '角色管理', keepAlive: true, permission: [ 'permission' ] }
}
]
},

View File

@@ -1,79 +0,0 @@
<template>
<a-modal :width="640" :visible="visible" title="任务添加" @ok="handleSubmit" @cancel="visible = false">
<a-form @submit="handleSubmit" :form="form">
<a-form-item
label="任务名称"
:labelCol="labelCol"
:wrapperCol="wrapperCol"
>
<a-input v-decorator="['taskName', {rules:[{required: true, message: '请输入任务名称'}]}]" />
</a-form-item>
<a-form-item
label="开始时间"
:labelCol="labelCol"
:wrapperCol="wrapperCol"
>
<a-date-picker style="width: 100%" v-decorator="['startTime', {rules:[{required: true, message: '请选择开始时间'}]}]" />
</a-form-item>
<a-form-item
label="任务负责人"
:labelCol="labelCol"
:wrapperCol="wrapperCol"
>
<a-select v-decorator="['owner', {rules:[{required: true, message: '请选择开始时间'}]}]">
<a-select-option :value="0">付晓晓</a-select-option>
<a-select-option :value="1">周毛毛</a-select-option>
</a-select>
</a-form-item>
<a-form-item
label="产品描述"
:labelCol="labelCol"
:wrapperCol="wrapperCol"
>
<a-textarea v-decorator="['desc']"></a-textarea>
</a-form-item>
</a-form>
</a-modal>
</template>
<script>
export default {
name: 'TaskForm',
data () {
return {
labelCol: {
xs: { span: 24 },
sm: { span: 7 }
},
wrapperCol: {
xs: { span: 24 },
sm: { span: 13 }
},
visible: false,
form: this.$form.createForm(this)
}
},
methods: {
add () {
this.visible = true
},
edit (record) {
const { form: { setFieldsValue } } = this
this.visible = true
this.$nextTick(() => {
setFieldsValue({ taskName: 'test' })
})
},
handleSubmit () {
const { form: { validateFields } } = this
this.visible = true
validateFields((errors, values) => {
if (!errors) {
console.log('values', values)
}
})
}
}
}
</script>

View File

@@ -0,0 +1,121 @@
<template>
<a-modal
:title="title"
:width="640"
:visible="visible"
:confirmLoading="confirmLoading"
@ok="handleSubmit"
@cancel="handleCancel"
>
<a-spin :spinning="confirmLoading">
<a-form :form="form">
<a-form-item
label="角色名称"
type="text"
:labelCol="labelCol"
:wrapperCol="wrapperCol"
>
<a-input v-decorator="['role_name', {rules: [{required: true, min: 3, message: '请输入至少3个字符'}]}]" />
</a-form-item>
<a-form-item
label="描述"
type="textarea"
:labelCol="labelCol"
:wrapperCol="wrapperCol"
>
<a-textarea v-decorator="['description']" />
</a-form-item>
</a-form>
</a-spin>
</a-modal>
</template>
<script>
import { store, update } from '@/api/role'
import pick from 'lodash.pick'
export default {
data () {
return {
labelCol: {
xs: { span: 24 },
sm: { span: 7 }
},
wrapperCol: {
xs: { span: 24 },
sm: { span: 13 }
},
visible: false,
title: '新建角色',
confirmLoading: false,
id: null,
parent_id: 0,
form: this.$form.createForm(this)
}
},
methods: {
add () {
this.visible = true
this.title = '新增角色'
},
edit (record) {
this.visible = true
this.title = '编辑角色'
const { form: { setFieldsValue } } = this
this.id = record.id
setFieldsValue(pick(record, ['role_name', 'description']))
},
addSon (record) {
this.visible = true
this.title = '新增子角色 (' + record.role_name + ')'
this.parent_id = record.id
},
handleSubmit () {
const { form: { validateFields } } = this
this.confirmLoading = true
if (this.id) {
validateFields((errors, values) => {
if (!errors) {
update(this.id, values).then((res) => {
this.refresh(res.message)
}).catch(err => this.failed(err))
}
})
} else {
validateFields((errors, values) => {
if (!errors) {
if (this.parent_id > 0) {
values['parent_id'] = this.parent_id
}
store(values).then((res) => {
this.refresh(res.message)
}).catch(err => this.failed(err))
}
})
}
},
failed (errors) {
this.$notification['error']({
message: errors.message,
duration: 4
})
this.handleCancel()
},
handleCancel () {
this.visible = false
this.id = null
this.confirmLoading = false
this.parent_id = 0
this.form.resetFields()
},
refresh (message) {
this.$notification['success']({
message: message,
duration: 4
})
this.handleCancel()
this.$parent.$parent.handleOk()
}
}
}
</script>

View File

@@ -0,0 +1,140 @@
<template>
<a-card :bordered="false">
<div class="table-page-search-wrapper">
<a-form layout="inline">
<a-row :gutter="48">
<a-col :md="4" :sm="24">
<a-input v-model="queryParam.role_name" placeholder="请输入角色名"/>
</a-col>
<a-col :md="4" :sm="24">
<span class="table-page-search-submitButtons">
<a-button type="primary" @click="$refs.table.refresh(true)">查询</a-button>
<a-button style="margin-left: 8px" @click="() => queryParam = {}">重置</a-button>
</span>
</a-col>
</a-row>
</a-form>
</div>
<div class="table-operator">
<a-button type="primary" icon="plus" @click="$refs.roleModal.add()">新建</a-button>
</div>
<s-table
ref="table"
size="default"
rowKey="id"
:bordered="true"
:columns="columns"
:data="loadData"
:showPagination="false"
>
<span slot="action" slot-scope="text, record">
<template>
<a @click="handleEdit(record)">编辑</a>
<a-divider type="vertical" />
<a @click="handleAddSon(record)">新增子角色</a>
<a-divider type="vertical" />
<a @click="handleDel(record)">删除</a>
</template>
</span>
</s-table>
<create-role ref="roleModal" @ok="handleOk" />
</a-card>
</template>
<script>
import moment from 'moment'
import { STable } from '@/components'
import CreateRole from './form/create'
import { getRoleList, del } from '@/api/role'
export default {
name: 'Users',
components: {
STable,
CreateRole
},
data () {
return {
// 查询参数
queryParam: {},
// 表头
columns: [
{
title: '角色名称',
dataIndex: 'role_name'
},
{
title: '描述',
dataIndex: 'description'
},
{
title: '创建时间',
dataIndex: 'created_at',
sorter: true
},
{
title: '更新时间',
dataIndex: 'updated_at',
sorter: true
},
{
title: '操作',
dataIndex: 'action',
width: '150px',
scopedSlots: { customRender: 'action' }
}
],
// 加载数据方法 必须为 Promise 对象
loadData: parameter => {
return getRoleList(Object.assign(parameter, this.queryParam))
.then(res => {
return res
})
}
}
},
methods: {
handleEdit (record) {
this.$refs.roleModal.edit(record)
},
handleAddSon (record) {
this.$refs.roleModal.addSon(record)
},
handleDel (record) {
this.$confirm({
title: '确定删除' + record.username + '吗?',
okText: '确定',
okType: 'danger',
cancelText: '取消',
onOk: () => {
del(record.id).then((res) => {
this.$notification['success']({
message: res.message,
duration: 4
})
this.handleOk()
}).catch(err => this.failed(err))
},
onCancel () {}
})
},
handleOk () {
this.$refs.table.refresh(true)
},
failed (errors) {
this.$notification['error']({
message: errors.message,
duration: 4
})
this.handleCancel()
},
resetSearchForm () {
this.queryParam = {
date: moment(new Date())
}
}
}
}
</script>

View File

@@ -45,7 +45,8 @@
<script>
import { validEmail } from '@/utils/validate'
import { store } from '@/api/user'
import { store, update } from '@/api/user'
import pick from 'lodash.pick'
export default {
data () {
@@ -60,7 +61,7 @@ export default {
},
visible: false,
confirmLoading: false,
id: null,
form: this.$form.createForm(this)
}
},
@@ -68,6 +69,12 @@ export default {
add () {
this.visible = true
},
edit (record) {
this.visible = true
const { form: { setFieldsValue } } = this
this.id = record.id
setFieldsValue(pick(record, ['username', 'email']))
},
handleEmail (rule, value, callback) {
if (!validEmail(value)) {
callback(new Error('邮箱地址不正确'))
@@ -77,31 +84,46 @@ export default {
handleSubmit () {
const { form: { validateFields } } = this
this.confirmLoading = true
validateFields((errors, values) => {
if (!errors) {
store(values).then((res) => {
this.$notification['success']({
message: res.data.message,
duration: 4
})
this.confirmLoading = false
this.form.resetFields()
this.handleOk()
this.handleCancel()
})
.catch(err => this.failed(err))
}
})
if (this.id) {
validateFields(['username', 'email'], (errors, values) => {
if (!errors) {
update(this.id, values).then((res) => {
this.refresh(res.message)
}).catch(err => this.failed(err))
}
})
} else {
validateFields((errors, values) => {
if (!errors) {
store(values).then((res) => {
this.refresh(res.message)
}).catch(err => this.failed(err))
}
})
}
},
failed (errors) {
this.$notification['error']({
message: errors.message,
duration: 4
})
this.confirmLoading = false
this.handleCancel()
},
handleCancel () {
handleCancel (message) {
this.id = null
this.visible = false
this.confirmLoading = false
this.form.resetFields()
},
refresh (message) {
this.$notification['success']({
message: message,
duration: 4
})
this.visible = false
this.form.resetFields()
this.id = null
this.$parent.$parent.handleOk()
}
}
}

View File

@@ -1,6 +1,6 @@
<template>
<a-modal
title="编辑用户"
title="新建用户"
:width="640"
:visible="visible"
:confirmLoading="confirmLoading"
@@ -29,14 +29,14 @@
:labelCol="labelCol"
:wrapperCol="wrapperCol"
>
<a-input type="password"/>
<a-input type="password" v-decorator="['password', {rules: [{required: true, min: 5, message: '请输入密码'}]}]" />
</a-form-item>
<a-form-item
label="确认密码"
:labelCol="labelCol"
:wrapperCol="wrapperCol"
>
<a-input type="password"/>
<a-input type="password" v-decorator="['passwordConfirm', {rules: [{required: true, min: 5, message: '请确认密码'}]}]" />
</a-form-item>
</a-form>
</a-spin>
@@ -44,12 +44,11 @@
</template>
<script>
import pick from 'lodash.pick'
import { validEmail } from '@/utils/validate'
import { update } from '@/api/user'
import { store, update } from '@/api/user'
import pick from 'lodash.pick'
export default {
name: 'EditUser',
data () {
return {
labelCol: {
@@ -62,16 +61,19 @@ export default {
},
visible: false,
confirmLoading: false,
mdl: {},
id: null,
form: this.$form.createForm(this)
}
},
methods: {
add () {
this.visible = true
},
edit (record) {
console.log(record)
this.visible = true
const { form: { setFieldsValue } } = this
setFieldsValue(pick({ username: '123' }))
this.id = record.id
setFieldsValue(pick(record, ['username', 'email']))
},
handleEmail (rule, value, callback) {
if (!validEmail(value)) {
@@ -81,33 +83,47 @@ export default {
},
handleSubmit () {
const { form: { validateFields } } = this
validateFields((errors, values) => {
if (!errors) {
this.confirmLoading = true
update(values).then((res) => {
this.$notification['success']({
message: res.data.message,
duration: 4
})
this.confirmLoading = false
this.destroy()
this.handleCancel()
})
.catch(err => this.failed(err))
}
})
this.confirmLoading = true
if (this.id) {
validateFields(['username', 'email'], (errors, values) => {
if (!errors) {
update(this.id, values).then((res) => {
this.refresh(res.message)
}).catch(err => this.failed(err))
}
})
} else {
validateFields((errors, values) => {
if (!errors) {
store(values).then((res) => {
this.refresh(res.message)
}).catch(err => this.failed(err))
}
})
}
},
failed (errors) {
this.$notification['error']({
message: errors.message,
duration: 4
})
this.confirmLoading = false
this.handleCancel()
},
handleCancel () {
console.log(12312)
// clear form & currentStep
handleCancel (message) {
this.id = null
this.visible = false
this.confirmLoading = false
this.form.resetFields()
},
refresh (message) {
this.$notification['success']({
message: message,
duration: 4
})
this.visible = false
this.form.resetFields()
this.id = null
this.$parent.$parent.handleOk()
}
}
}

View File

@@ -16,7 +16,7 @@
</a-select>
</a-col>
<a-col :md="4" :sm="24">
<span class="table-page-search-submitButtons" :style="advanced && { float: 'right', overflow: 'hidden' } || {} ">
<span class="table-page-search-submitButtons">
<a-button type="primary" @click="$refs.table.refresh(true)">查询</a-button>
<a-button style="margin-left: 8px" @click="() => queryParam = {}">重置</a-button>
</span>
@@ -26,13 +26,12 @@
</div>
<div class="table-operator">
<a-button type="primary" icon="plus" @click="$refs.createModal.add()">新建</a-button>
<a-button type="dashed" @click="tableOption">{{ optionAlertShow && '关闭' || '开启' }} alert</a-button>
<a-button type="primary" icon="plus" @click="$refs.userModal.add()">新建</a-button>
<a-dropdown v-action:edit v-if="selectedRowKeys.length > 0">
<a-menu slot="overlay">
<a-menu-item key="1"><a-icon type="delete" />删除</a-menu-item>
<a-menu-item @click="multiDel()"><a-icon type="delete"/>删除</a-menu-item>
<!-- lock | unlock -->
<a-menu-item key="2"><a-icon type="lock" />禁用</a-menu-item>
<a-menu-item @click="multiAble()"><a-icon type="lock"/>启用/禁用</a-menu-item>
</a-menu>
<a-button style="margin-left: 8px">
批量操作 <a-icon type="down" />
@@ -43,87 +42,47 @@
<s-table
ref="table"
size="default"
rowKey="key"
rowKey="id"
:bordered="true"
:columns="columns"
:data="loadData"
:alert="options.alert"
:rowSelection="options.rowSelection"
showPagination="auto"
>
<span slot="serial" slot-scope="text, record, index">
{{ index + 1 }}
</span>
<span slot="status" slot-scope="text">
<a-badge :status="text | statusTypeFilter" :text="text | statusFilter" />
</span>
<span slot="description" slot-scope="text">
<ellipsis :length="4" tooltip>{{ text }}</ellipsis>
</span>
<span slot="action" slot-scope="text, record">
<template>
<a @click="handleEdit(record)">编辑</a>
<a-divider type="vertical" />
<a @click="handleSub(record)">删除</a>
<a @click="handleDel(record)">删除</a>
</template>
</span>
</s-table>
<create-form ref="createModal" @ok="handleOk" />
<edit-user ref="modal" @ok="handleOk"/>
<create-user ref="userModal" @ok="handleOk" />
</a-card>
</template>
<script>
import moment from 'moment'
import { STable, Ellipsis } from '@/components'
import EditUser from './modules/EditUser'
import CreateForm from './modules/CreateForm'
import { getRoleList, getUserList } from '@/api/manage'
import { switchStatus } from '@/api/user'
const statusMap = {
0: {
status: 'default',
text: '关闭'
},
1: {
status: 'processing',
text: '运行中'
},
2: {
status: 'success',
text: '已上线'
},
3: {
status: 'error',
text: '异常'
}
}
import { STable } from '@/components'
import CreateUser from './form/create'
import { swtichStatus, del, getUserList } from '@/api/user'
export default {
name: 'TableList',
name: 'Users',
components: {
STable,
Ellipsis,
CreateForm,
EditUser
CreateUser
},
data () {
return {
mdl: {},
// /
advanced: false,
//
queryParam: {},
//
columns: [
{
title: '#',
scopedSlots: { customRender: 'serial' }
},
{
title: '用户ID',
dataIndex: 'id'
key: 'id'
},
{
title: '用户名',
@@ -164,83 +123,82 @@ export default {
},
selectedRowKeys: [],
selectedRows: [],
// custom table alert & rowSelection
options: {
alert: { show: true, clear: () => { this.selectedRowKeys = [] } },
alert: { show: false, clear: () => { this.selectedRowKeys = [] } },
rowSelection: {
selectedRowKeys: this.selectedRowKeys,
onChange: this.onSelectChange
}
},
optionAlertShow: false
}
},
filters: {
statusFilter (type) {
return statusMap[type].text
},
statusTypeFilter (type) {
return statusMap[type].status
}
}
},
created () {
this.tableOption()
getRoleList({ t: new Date() })
// this.tableOption()
},
methods: {
tableOption () {
if (!this.optionAlertShow) {
this.options = {
alert: { show: true, clear: () => { this.selectedRowKeys = [] } },
rowSelection: {
selectedRowKeys: this.selectedRowKeys,
onChange: this.onSelectChange,
getCheckboxProps: record => ({
props: {
disabled: record.no === 'No 2', // Column configuration not to be checked
name: record.no
}
})
}
}
this.optionAlertShow = true
} else {
this.options = {
alert: false,
rowSelection: null
}
this.optionAlertShow = false
}
},
renderStatus (value, row, index) {
return value === 1 ? <a-switch checkedChildren="正常" unCheckedChildren="禁用" defaultChecked onClick={this.handleSwitch} />
: <a-switch checkedChildren="正常" id={row.id} unCheckedChildren="禁用" onClick={this.handleSwitch}/>
return value === 1 ? <a-button type="normal" size="small">正常</a-button> : <a-button type="danger" size="small">禁用</a-button>
},
handleEdit (record) {
this.$refs.modal.edit(record)
this.$refs.userModal.edit(record)
},
handleSwitch (checked, event) {
console.log(event)
switchStatus()
},
handleSub (record) {
if (record.status !== 0) {
this.$message.info(`${record.no} 订阅成功`)
} else {
this.$message.error(`${record.no} 订阅失败,规则已关闭`)
}
handleDel (record) {
this.$confirm({
title: '确定删除' + record.username + '吗?',
okText: '确定',
okType: 'danger',
cancelText: '取消',
onOk: () => {
del(record.id).then((res) => {
this.$notification['success']({
message: res.message,
duration: 4
})
this.handleOk()
})
},
onCancel () {}
})
},
handleOk () {
this.$refs.table.refresh()
this.$refs.table.refresh(true)
},
multiDel () {
this.$confirm({
title: '确定批量删除吗?',
okText: '确定',
okType: 'danger',
cancelText: '取消',
onOk: () => {
del(this.selectedRowKeys.join(',')).then((res) => {
this.$notification['success']({
message: res.message,
duration: 4
})
this.selectedRowKeys = []
this.handleOk()
})
},
onCancel () {}
})
},
multiAble () {
swtichStatus(this.selectedRowKeys.join(',')).then((res) => {
this.$notification['success']({
message: res.message,
duration: 4
})
console.log(this.selectedRowKeys)
// this.options.rowSelection
this.onSelectChange([], [])
this.handleOk()
})
},
onSelectChange (selectedRowKeys, selectedRows) {
this.selectedRowKeys = selectedRowKeys
this.selectedRows = selectedRows
},
toggleAdvanced () {
this.advanced = !this.advanced
},
resetSearchForm () {
this.queryParam = {
date: moment(new Date())