update
This commit is contained in:
parent
61273892d8
commit
bfc7805172
|
|
@ -28,7 +28,11 @@
|
|||
:pagination="pagination"
|
||||
@update:page="updatePage"
|
||||
@update:page-size="updatePageSize"
|
||||
/>
|
||||
>
|
||||
<template #empty>
|
||||
<slot name="empty" />
|
||||
</template>
|
||||
</n-data-table>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
|
|||
|
|
@ -50,7 +50,10 @@ export default defineComponent({
|
|||
const getActions = computed(() => {
|
||||
return (toRaw(props.actions) || [])
|
||||
.filter((action) => {
|
||||
return data.permissionList.includes(action.auth) || action.auth === ''
|
||||
if (!Object.keys(action).includes('show')) {
|
||||
action.show = Object.keys(action).includes('hidden') ? !action.hidden : true
|
||||
}
|
||||
return (data.permissionList.includes(action.auth) || action.auth === '') && action.show
|
||||
})
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -58,10 +58,10 @@ export default defineComponent({
|
|||
const { filters } = unref(props)
|
||||
function getFilter(value) {
|
||||
const data = filters.find(item => {
|
||||
return item.key === value
|
||||
return item.value === value
|
||||
})
|
||||
return data || {
|
||||
key: value,
|
||||
value: value,
|
||||
label: value
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,6 +29,8 @@ export const tableProps = {
|
|||
pageField: 'page',
|
||||
// 每页数量字段名
|
||||
sizeField: 'limit',
|
||||
// 接口返回的字段名
|
||||
listPageField: 'current',
|
||||
// 接口返回的数据字段名
|
||||
listField: 'records',
|
||||
// 接口返回总页数字段名
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import { toTreeData } from './toTree'
|
|||
|
||||
export function useDataSource(propsRef, { getPaginationInfo, setPagination, setLoading, tableData }, emit) {
|
||||
const dataSourceRef = ref([])
|
||||
|
||||
const paginationPage = ref(1)
|
||||
async function fetch(opt) {
|
||||
try {
|
||||
/* 设置loading */
|
||||
|
|
@ -14,6 +14,7 @@ export function useDataSource(propsRef, { getPaginationInfo, setPagination, setL
|
|||
if (!request) return
|
||||
/* 获取分页信息 */
|
||||
const pageField = paginationSetting.pageField
|
||||
const listPageField = paginationSetting.listPageField
|
||||
const sizeField = paginationSetting.sizeField
|
||||
const totalField = paginationSetting.totalField
|
||||
const listField = paginationSetting.listField
|
||||
|
|
@ -25,6 +26,7 @@ export function useDataSource(propsRef, { getPaginationInfo, setPagination, setL
|
|||
pageParams = {}
|
||||
} else {
|
||||
pageParams[pageField] = (opt && opt[pageField]) || page
|
||||
paginationPage.value = pageParams[pageField]
|
||||
pageParams[sizeField] = pageSize
|
||||
}
|
||||
const params = {
|
||||
|
|
@ -33,7 +35,7 @@ export function useDataSource(propsRef, { getPaginationInfo, setPagination, setL
|
|||
const response = await request(params)
|
||||
const res = noPagination ? response : response.data
|
||||
const resultTotal = res[totalField] || 0
|
||||
const currentPage = res[pageField]
|
||||
const currentPage = res[listPageField]
|
||||
// 如果数据异常,需获取正确的页码再次执行
|
||||
if (resultTotal) {
|
||||
if (page > Math.ceil(resultTotal / pageSize)) {
|
||||
|
|
@ -45,10 +47,11 @@ export function useDataSource(propsRef, { getPaginationInfo, setPagination, setL
|
|||
}
|
||||
// 处理数据结构
|
||||
const resultInfo = res[listField] ? res[listField] : res
|
||||
dataSourceRef.value = dataType === 'tree' ? dealTree(resultInfo) : resultInfo
|
||||
dataSourceRef.value = dataType === 'tree' ? dealTree(resultInfo.data) : resultInfo
|
||||
setPagination({
|
||||
[pageField]: currentPage,
|
||||
[totalField]: Math.ceil(resultTotal / pageSize)
|
||||
[totalField]: Math.ceil(resultTotal / pageSize),
|
||||
itemCount: resultTotal
|
||||
})
|
||||
/* 更新页码数据 */
|
||||
if (opt && opt[pageField]) {
|
||||
|
|
@ -105,13 +108,13 @@ export function useDataSource(propsRef, { getPaginationInfo, setPagination, setL
|
|||
await fetch(opt)
|
||||
}
|
||||
|
||||
async function reFetch(opt) {
|
||||
async function reFetch(opt, reload = true) {
|
||||
const { paginationSetting } = unref(propsRef)
|
||||
const pageField = paginationSetting.pageField
|
||||
const sizeField = paginationSetting.sizeField
|
||||
const pageSize = paginationSetting.pageSize
|
||||
setPagination({
|
||||
[pageField]: 1,
|
||||
[pageField]: reload ? 1 : paginationPage.value,
|
||||
[sizeField]: pageSize
|
||||
})
|
||||
await fetch(opt)
|
||||
|
|
|
|||
|
|
@ -17,7 +17,10 @@ export function usePagination(refProps) {
|
|||
showQuickJumper: paginationSetting.showQuickJumper,
|
||||
...(isBoolean(pagination) ? {} : pagination),
|
||||
...unref(configRef),
|
||||
pageCount: unref(configRef)[paginationSetting.totalField]
|
||||
pageCount: unref(configRef)[paginationSetting.totalField],
|
||||
prefix({ itemCount }) {
|
||||
return `共 ${itemCount} 条`
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
<template>
|
||||
<n-modal
|
||||
ref="modalRef"
|
||||
v-bind="getModalOptions"
|
||||
:style="`width:${getModalOptions.width}px`"
|
||||
:title="options.title"
|
||||
|
|
@ -12,7 +13,7 @@
|
|||
|
||||
<script>
|
||||
|
||||
import { defineComponent, computed } from 'vue'
|
||||
import { defineComponent, computed, ref } from 'vue'
|
||||
export default defineComponent({
|
||||
name: 'CardDialogModal',
|
||||
props: {
|
||||
|
|
@ -28,6 +29,7 @@ export default defineComponent({
|
|||
}
|
||||
},
|
||||
setup(props, { emit }) {
|
||||
const modalRef = ref(null)
|
||||
const getModalOptions = computed(() => {
|
||||
return {
|
||||
...props.options,
|
||||
|
|
@ -43,7 +45,45 @@ export default defineComponent({
|
|||
const handleClose = function() {
|
||||
emit('onClose', true)
|
||||
}
|
||||
|
||||
// setTimeout(() => {
|
||||
// const dialogHeaderEl = document.querySelector('.n-card-header')
|
||||
// const dragDom = document.querySelector('.n-modal')
|
||||
// dragDom.style.overflow = 'auto'
|
||||
// dialogHeaderEl.style.cursor = 'move'
|
||||
// const sty = dragDom.currentStyle || window.getComputedStyle(dragDom, null)
|
||||
// const moveDown = (e) => {
|
||||
// // 鼠标按下,计算当前元素距离可视区的距离
|
||||
// const disX = e.clientX - dialogHeaderEl.offsetLeft
|
||||
// const disY = e.clientY - dialogHeaderEl.offsetTop
|
||||
// // 获取到的值带px 正则匹配替换
|
||||
// let styL, styT
|
||||
// // 注意在ie中 第一次获取到的值为组件自带50% 移动之后赋值为px
|
||||
// if (sty.left.includes('%')) {
|
||||
// styL = +document.body.clientWidth * (+sty.left.replace(/\%/g, '') / 100)
|
||||
// styT = +document.body.clientHeight * (+sty.top.replace(/\%/g, '') / 100)
|
||||
// } else {
|
||||
// styL = +sty.left.replace(/\px/g, '')
|
||||
// styT = +sty.top.replace(/\px/g, '')
|
||||
// }
|
||||
// document.onmousemove = function(e) {
|
||||
// // 计算移动的距离
|
||||
// const l = e.clientX - disX
|
||||
// const t = e.clientY - disY
|
||||
// // 移动当前元素
|
||||
// dragDom.style.left = `${l + styL}px`
|
||||
// dragDom.style.top = `${t + styT}px`
|
||||
// }
|
||||
// document.onmouseup = function(e) {
|
||||
// document.onmousemove = null
|
||||
// document.onmouseup = null
|
||||
// }
|
||||
// }
|
||||
// dialogHeaderEl.onmousedown = moveDown
|
||||
// })
|
||||
|
||||
return {
|
||||
modalRef,
|
||||
getModalOptions,
|
||||
handleConfirm,
|
||||
handleClose
|
||||
|
|
@ -53,4 +93,9 @@ export default defineComponent({
|
|||
</script>
|
||||
|
||||
<style scoped lang='scss'>
|
||||
::v-deep(.n-scrollbar-content){
|
||||
&:first-child{
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -2,21 +2,15 @@
|
|||
<div>
|
||||
<n-form ref="formRef" v-bind="getFormOptions">
|
||||
<template v-for="(item, index) in getFormOptions.info" :key="`${index}-${item.label}`">
|
||||
<n-form-item v-if="['input'].includes(item.type) || !item.type" :label="item.label">
|
||||
<n-input v-model:value="getFormOptions.form[item.key]" v-bind="item.props" />
|
||||
</n-form-item>
|
||||
<n-form-item v-if="['select'].includes(item.type) " :label="item.label">
|
||||
<n-select v-model:value="getFormOptions.form[item.key]" v-bind="item.props" />
|
||||
</n-form-item>
|
||||
<n-form-item v-if="['area'].includes(item.type) " :label="item.label">
|
||||
<AreaCascader :ref="el=>{itemRefs[item.refIndex] = el}" v-model:value="getFormOptions.form[item.key]" v-bind="item.props" @selectd="handleSelect" />
|
||||
</n-form-item>
|
||||
<n-form-item v-if="['date'].includes(item.type) " :label="item.label">
|
||||
<n-date-picker v-model="getFormOptions.form[item.key]" v-bind="item.props" />
|
||||
<n-form-item :class="{'hidden-item': index > showItemNum}" :label="item.label">
|
||||
<n-input v-if="['input'].includes(item.type) || !item.type" v-model:value="getFormOptions.form[item.key]" v-bind="item.props" />
|
||||
<n-select v-if="['select'].includes(item.type)" v-model:value="getFormOptions.form[item.key]" v-bind="item.props" />
|
||||
<AreaCascader v-if="['area'].includes(item.type)" :ref="el=>{itemRefs[item.refIndex] = el}" v-model:value="getFormOptions.form[item.key]" v-bind="item.props" @selectd="handleSelect" />
|
||||
<n-date-picker v-if="['date'].includes(item.type)" v-model:formatted-value="getFormOptions.form[item.key]" v-bind="item.props" />
|
||||
</n-form-item>
|
||||
</template>
|
||||
<n-form-item class="form__button">
|
||||
<n-button @click="handleSearch">查询</n-button>
|
||||
<n-button type="primary" @click="handleSearch">查询</n-button>
|
||||
<n-button @click="handleReset">重置</n-button>
|
||||
<n-button
|
||||
v-if="showButton"
|
||||
|
|
@ -29,7 +23,7 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { computed, ref, unref } from 'vue'
|
||||
import { computed, ref, unref, watch } from 'vue'
|
||||
import { NForm } from 'naive-ui'
|
||||
import AreaCascader from '@/components/AreaCascader/index.vue'
|
||||
export default {
|
||||
|
|
@ -42,9 +36,9 @@ export default {
|
|||
default: () => []
|
||||
}
|
||||
},
|
||||
emits: ['search', 'reset'],
|
||||
emits: ['search', 'change', 'reset'],
|
||||
setup(props, { emit }) {
|
||||
const showItemNum = ref(3)
|
||||
const showItemNum = ref(30)
|
||||
const len = ref(props.info.length - 1)
|
||||
const itemRefs = ref([])
|
||||
const showButton = ref(!!(showItemNum.value < len.value))
|
||||
|
|
@ -52,12 +46,14 @@ export default {
|
|||
/* 初始化搜索表单信息 */
|
||||
function initForm() {
|
||||
Object.keys(form.value).forEach((key) => {
|
||||
form.value[key] = null
|
||||
const index = unref(props).info.findIndex((item) => item.key === key)
|
||||
form.value[key] = (props).info[index].value || null
|
||||
})
|
||||
itemRefs.value.forEach((item) => {
|
||||
item.clearValue()
|
||||
})
|
||||
}
|
||||
/* 地图选择事件 */
|
||||
function handleSelect(data) {
|
||||
form.value = {
|
||||
...form.value,
|
||||
|
|
@ -65,21 +61,42 @@ export default {
|
|||
}
|
||||
}
|
||||
const getFormOptions = computed(() => {
|
||||
props.info.forEach((item) => {
|
||||
// const hasInit = item.init || false
|
||||
// const hasKey = Object.keys(form.value).includes(item.key)
|
||||
// form.value[item.key] = hasInit ? (item.value || null) : hasKey ? form.value[item.key] : (item.value || null)
|
||||
form.value[item.key] = item.value || null
|
||||
})
|
||||
return {
|
||||
form: unref(form),
|
||||
labelWidth: 'auto',
|
||||
labelPlacement: 'left',
|
||||
inline: true,
|
||||
info: [...unref(props).info]
|
||||
info: [...props.info]
|
||||
}
|
||||
})
|
||||
|
||||
watch(getFormOptions.value.form,
|
||||
(value) => {
|
||||
emit('change', getFormOptions.value.form)
|
||||
})
|
||||
|
||||
function handleSearch() {
|
||||
emit('search', getFormOptions.value.form)
|
||||
}
|
||||
|
||||
function handleReset() {
|
||||
initForm()
|
||||
emit('reset', getFormOptions.value.form)
|
||||
}
|
||||
|
||||
function setFormValue(params) {
|
||||
Object.keys(params).forEach((key) => {
|
||||
const index = unref(props).info.findIndex((item) => item.key === key)
|
||||
form.value[key] = (props).info[index].value || null
|
||||
})
|
||||
}
|
||||
|
||||
function showMoreItem() {
|
||||
showItemNum.value = showItemNum.value === len.value ? 3 : len.value
|
||||
}
|
||||
|
|
@ -89,6 +106,7 @@ export default {
|
|||
getFormOptions,
|
||||
handleSearch,
|
||||
handleReset,
|
||||
setFormValue,
|
||||
handleSelect,
|
||||
itemRefs,
|
||||
showMoreItem
|
||||
|
|
@ -111,6 +129,9 @@ export default {
|
|||
.n-cascader{
|
||||
width: 200px;
|
||||
}
|
||||
&.hidden-item{
|
||||
display: none;
|
||||
}
|
||||
transition: all 10s;
|
||||
}
|
||||
.form__button{
|
||||
|
|
|
|||
|
|
@ -0,0 +1,73 @@
|
|||
<template>
|
||||
<div v-if="external" :style="styleExternalIcon" class="svg-external-icon svg-icon" v-bind="$attrs" />
|
||||
<svg v-else :class="svgClass" aria-hidden="true" v-bind="$attrs">
|
||||
<use :xlink:href="iconName" />
|
||||
</svg>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { isExternal } from '@/utils/is.js'
|
||||
import { defineComponent, computed } from 'vue'
|
||||
export default defineComponent({
|
||||
name: 'SvgIcon',
|
||||
props: {
|
||||
prefix: {
|
||||
type: String,
|
||||
default: 'icon'
|
||||
},
|
||||
iconClass: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
className: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
setup(props, { emit }) {
|
||||
const external = computed(() => {
|
||||
return isExternal(props.iconClass)
|
||||
})
|
||||
|
||||
const iconName = computed(() => {
|
||||
return `#icon-${props.iconClass}`
|
||||
})
|
||||
|
||||
const svgClass = computed(() => {
|
||||
if (props.className) {
|
||||
return 'svg-icon ' + props.className
|
||||
} else {
|
||||
return 'svg-icon'
|
||||
}
|
||||
})
|
||||
const styleExternalIcon = computed(() => {
|
||||
return {
|
||||
mask: `url(${props.iconClass}) no-repeat 50% 50%`,
|
||||
'-webkit-mask': `url(${props.iconClass}) no-repeat 50% 50%`
|
||||
}
|
||||
})
|
||||
return {
|
||||
external,
|
||||
iconName,
|
||||
svgClass,
|
||||
styleExternalIcon
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.svg-icon {
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
vertical-align: -0.15em;
|
||||
fill: currentColor;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.svg-external-icon {
|
||||
background-color: currentColor;
|
||||
mask-size: cover!important;
|
||||
display: inline-block;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,176 @@
|
|||
<template>
|
||||
<div v-if="isFailed && useEmpty">
|
||||
<slot name="empty" />
|
||||
</div>
|
||||
<div v-else :id="getPlayerId" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import { defineComponent, reactive, ref, computed, toRefs, nextTick } from 'vue'
|
||||
export default defineComponent({
|
||||
name: 'VideoPlayer',
|
||||
props: {
|
||||
/* 播放器id */
|
||||
id: {
|
||||
type: String,
|
||||
default: () => 'palyer'
|
||||
},
|
||||
/* 是有填充空白 */
|
||||
useEmpty: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
emits: ['timeUpdate', 'video-status'],
|
||||
setup(props, { emit }) {
|
||||
const videoPlayer = Symbol.for(props.id)
|
||||
const data = reactive({
|
||||
[videoPlayer]: null,
|
||||
seekTime: null,
|
||||
canSeek: true,
|
||||
isSeek: false,
|
||||
isFailed: true
|
||||
})
|
||||
/* 获取播放器的id */
|
||||
const getPlayerId = computed(() => {
|
||||
return props.id
|
||||
})
|
||||
|
||||
/* 播放器组件 */
|
||||
const toolComponent = Aliplayer.Component({
|
||||
/* 时间更新事件 */
|
||||
timeupdate(player, e) {
|
||||
data.seekTime = player.getCurrentTime()
|
||||
emit('video-status', data.isSeek ? 'skip' : 'playing')
|
||||
},
|
||||
ready(player, e) {
|
||||
emit('video-status', 'ready')
|
||||
},
|
||||
pause(player, e) {
|
||||
emit('video-status', 'pause')
|
||||
},
|
||||
play(player, e) {
|
||||
emit('video-status', 'play')
|
||||
},
|
||||
ended(player, e) {
|
||||
emit('video-status', 'ended')
|
||||
},
|
||||
error(player, e) {
|
||||
data.isFailed = true
|
||||
emit('video-status', 'error')
|
||||
}
|
||||
})
|
||||
|
||||
/* 初始化播放器 */
|
||||
function init(options) {
|
||||
if (!options.source) {
|
||||
data.isFailed = true
|
||||
} else {
|
||||
data.isFailed = false
|
||||
nextTick(() => {
|
||||
/* 实例化ali播放器 */
|
||||
const player = new Aliplayer(
|
||||
{
|
||||
id: props.id,
|
||||
width: '500px',
|
||||
height: '260px',
|
||||
autoplay: true,
|
||||
...options,
|
||||
components: [toolComponent]
|
||||
},
|
||||
function(player) { player.mute() }
|
||||
)
|
||||
/* 监听开始拖拽事件 */
|
||||
player.on('startSeek', ({ paramData }) => {
|
||||
/* 仅变更标识 */
|
||||
data.isSeek = true
|
||||
})
|
||||
/* 监听完成拖拽事件 */
|
||||
player.on('completeSeek', ({ paramData }) => {
|
||||
/* 仅变更标识 */
|
||||
data.isSeek = false
|
||||
data.seekTime = paramData
|
||||
/* 是否通知跳转 */
|
||||
if (data.canSeek) {
|
||||
emit('video-status', 'skip')
|
||||
}
|
||||
})
|
||||
data[videoPlayer] = player
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/* 获取当前播放器的时间 */
|
||||
function getTime() {
|
||||
let currentTime = 0
|
||||
let duration = 0
|
||||
const seekTime = data.seekTime
|
||||
if (data[videoPlayer] && !data.isFailed) {
|
||||
currentTime = data[videoPlayer]?.getCurrentTime()
|
||||
duration = data[videoPlayer]?.getDuration()
|
||||
}
|
||||
return {
|
||||
currentTime,
|
||||
duration,
|
||||
seekTime
|
||||
}
|
||||
}
|
||||
/* 设定播放器播放时间 */
|
||||
function seekTime(time) {
|
||||
if (data[videoPlayer] && !data.isFailed) {
|
||||
data.canSeek = false
|
||||
data[videoPlayer]?.seek(time)
|
||||
setTimeout(() => {
|
||||
data.canSeek = true
|
||||
}, 100)
|
||||
}
|
||||
}
|
||||
/* 设定播放器开始 */
|
||||
function playVideo() {
|
||||
if (data[videoPlayer] && !data.isFailed) {
|
||||
data[videoPlayer]?.play()
|
||||
}
|
||||
}
|
||||
/* 设定播放器暂停 */
|
||||
function pauseVideo() {
|
||||
if (data[videoPlayer] && !data.isFailed) {
|
||||
data[videoPlayer]?.pause()
|
||||
}
|
||||
}
|
||||
/* 销毁播放器 */
|
||||
function disposeVideo() {
|
||||
if (data[videoPlayer] && !data.isFailed) {
|
||||
data[videoPlayer]?.dispose()
|
||||
}
|
||||
data.isFailed = true
|
||||
}
|
||||
|
||||
return {
|
||||
...toRefs(data),
|
||||
getPlayerId,
|
||||
init,
|
||||
getTime,
|
||||
seekTime,
|
||||
playVideo,
|
||||
pauseVideo,
|
||||
disposeVideo
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
</script>
|
||||
<style>
|
||||
.prism-player .prism-ErrorMessage .prism-error-operation{
|
||||
border-bottom: none;
|
||||
}
|
||||
.prism-player .prism-ErrorMessage .prism-error-operation a.prism-button.prism-button-refresh{
|
||||
display: none;
|
||||
}
|
||||
.prism-player .prism-ErrorMessage .prism-error-operation a.prism-button.prism-button-orange{
|
||||
display: none;
|
||||
}
|
||||
/* .prism-player .prism-ErrorMessage .prism-detect-info.prism-center{
|
||||
display: none;
|
||||
} */
|
||||
</style>
|
||||
|
|
@ -3,16 +3,45 @@ export default [
|
|||
{
|
||||
path: '/system',
|
||||
component: Layout,
|
||||
redirect: '/system/menu',
|
||||
redirect: '/system/user',
|
||||
name: 'System',
|
||||
title: '系统管理',
|
||||
meta: {
|
||||
title: '系统管理'
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: 'user',
|
||||
component: () => import('@/views/system-manage/user-manage/index.vue'),
|
||||
name: 'SystemUser',
|
||||
title: '用户管理',
|
||||
meta: {
|
||||
title: '用户管理'
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'role',
|
||||
component: () => import('@/views/system-manage/role-manage/index.vue'),
|
||||
name: 'SystemRole',
|
||||
title: '角色管理',
|
||||
meta: {
|
||||
title: '角色管理'
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'dept',
|
||||
component: () => import('@/views/system-manage/department-manage/index.vue'),
|
||||
name: 'SystemDept',
|
||||
title: '部门管理',
|
||||
meta: {
|
||||
title: '部门管理'
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'menu',
|
||||
component: () => import('@/views/system/menu/index.vue'),
|
||||
component: () => import('@/views/system-manage/menu-manage/index.vue'),
|
||||
name: 'SystemMenu',
|
||||
title: '菜单管理',
|
||||
meta: {
|
||||
title: '菜单管理'
|
||||
}
|
||||
|
|
|
|||
|
|
@ -105,7 +105,7 @@ export default {
|
|||
}
|
||||
|
||||
/* 调用store中的方法,登录以及存储token和用户信息 */
|
||||
const res = await userStore.getLoginToken(this.loginForm)
|
||||
const res = await userStore.getLoginToken(data.loginForm)
|
||||
if (res.code === 0) {
|
||||
const toPath = decodeURIComponent((route.query?.redirect || '/'))
|
||||
route.name === '/login' ? router.replace('/') : router.replace(toPath)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,139 @@
|
|||
<template>
|
||||
<Modal
|
||||
:options="getModalOptions"
|
||||
:on-positive-click="handleConfirm"
|
||||
:on-negative-click="handleClose"
|
||||
:on-close="handleClose"
|
||||
>
|
||||
<template #Context>
|
||||
<n-form
|
||||
ref="formRef"
|
||||
:model="departmentForm"
|
||||
:rules="departmentRules"
|
||||
:label-width="80"
|
||||
label-placement="left"
|
||||
require-mark-placement="left"
|
||||
:disabled="disabled"
|
||||
>
|
||||
<template v-for="(item,index) in getFormOptions" :key="index">
|
||||
<n-form-item :label="item.label" :path="item.key">
|
||||
<n-input v-if="item.type === 'input'" v-model:value="departmentForm[item.key]" v-bind="item.props" />
|
||||
<n-select v-if="item.type === 'select'" v-model:value="departmentForm[item.key]" v-bind="item.props" />
|
||||
<n-input-number v-if="item.type === 'number'" v-model:value="departmentForm[item.key]" v-bind="item.props" />
|
||||
</n-form-item>
|
||||
</template>
|
||||
|
||||
</n-form>
|
||||
</template>
|
||||
</Modal>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { form, getDeptOptions } from '../tools/form.js'
|
||||
import Modal from '@/components/Modal/index.vue'
|
||||
import { addDept, editDept } from '@/api/system/dept/index.js'
|
||||
import { defineComponent, ref, reactive, computed, toRefs } from 'vue'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'UserModal',
|
||||
components: { Modal },
|
||||
props: {
|
||||
visible: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
default: 'create'
|
||||
},
|
||||
data: {
|
||||
type: Object,
|
||||
default: () => {}
|
||||
}
|
||||
},
|
||||
emits: {
|
||||
'update:visible': null,
|
||||
'reload': null
|
||||
},
|
||||
setup(props, { emit }) {
|
||||
const MODAL_TYPE = {
|
||||
'create': '新建部门',
|
||||
'preview': '部门详情',
|
||||
'update': '编辑部门'
|
||||
}
|
||||
getDeptOptions()
|
||||
const { departmentForm, departmentRules } = form
|
||||
const formRef = ref()
|
||||
const data = reactive({
|
||||
departmentForm: {
|
||||
...departmentForm,
|
||||
...props.data,
|
||||
pid: props.data?.pid === 0 ? null : props.data?.pid
|
||||
},
|
||||
departmentRules: {
|
||||
...departmentRules
|
||||
},
|
||||
disabled: props.type === 'preview'
|
||||
})
|
||||
const getModalOptions = computed(() => {
|
||||
return {
|
||||
title: MODAL_TYPE[props.type],
|
||||
show: props.visible,
|
||||
negativeText: '取消',
|
||||
positiveText: '确认'
|
||||
}
|
||||
})
|
||||
|
||||
const getFormOptions = computed(() => {
|
||||
return {
|
||||
...form.formItem
|
||||
}
|
||||
})
|
||||
|
||||
function handleConfirm() {
|
||||
formRef.value.validate((errors) => {
|
||||
if (!errors) {
|
||||
const params = { ...data.departmentForm }
|
||||
if (params.id) {
|
||||
editDept(params).then(res => {
|
||||
if (res.code === 0) {
|
||||
emit('reload')
|
||||
handleClose()
|
||||
}
|
||||
}).catch(e => {
|
||||
console.log(e)
|
||||
})
|
||||
} else {
|
||||
addDept(params).then(res => {
|
||||
if (res.code === 0) {
|
||||
emit('reload')
|
||||
handleClose()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/* 关闭弹窗 */
|
||||
const handleClose = () => {
|
||||
emit('update:visible', false)
|
||||
}
|
||||
|
||||
return {
|
||||
...toRefs(data),
|
||||
formRef,
|
||||
getModalOptions,
|
||||
getFormOptions,
|
||||
handleConfirm,
|
||||
handleClose
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang='scss'>
|
||||
.n-input-number{
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
<template>
|
||||
<div>
|
||||
<n-card>
|
||||
<headSearch :info="search" @search="handleSearch" @reset="handleSearch" />
|
||||
<data-table
|
||||
ref="tableRef"
|
||||
:columns="columns"
|
||||
:request="loadDataTable"
|
||||
:row-key="(row) => row.id"
|
||||
:pagination="false"
|
||||
data-type="tree"
|
||||
size="large"
|
||||
>
|
||||
<template #tableTitle>
|
||||
<n-button type="primary" @click="handleModal"> 新建 </n-button>
|
||||
</template>
|
||||
</data-table>
|
||||
</n-card>
|
||||
</div>
|
||||
<!-- 新增、编辑弹窗 -->
|
||||
<DepartmentModal v-if="modalShow" v-model:visible="modalShow" :data="rowData" :type="modalType" @reload="handleSearch" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import search from './tools/search.js'
|
||||
import table from './tools/table.js'
|
||||
import headSearch from '@/components/Search/index.vue'
|
||||
import dataTable from '@/components/DataTable/index.vue'
|
||||
import DepartmentModal from './components/DepartmentModal.vue'
|
||||
import { getDeptList } from '@/api/system/dept/index.js'
|
||||
import { unref, toRefs, reactive, onUnmounted } from 'vue'
|
||||
|
||||
export default {
|
||||
name: 'MenuPage',
|
||||
components: { dataTable, DepartmentModal, headSearch },
|
||||
setup() {
|
||||
const data = reactive({
|
||||
...toRefs(table),
|
||||
search
|
||||
})
|
||||
|
||||
const loadDataTable = async(res) => {
|
||||
const _params = {
|
||||
...unref(data.searchParams),
|
||||
...res
|
||||
}
|
||||
return await getDeptList(_params)
|
||||
}
|
||||
|
||||
// 新增
|
||||
function handleModal() {
|
||||
data.rowData = null
|
||||
data.modalType = 'create'
|
||||
data.modalShow = true
|
||||
}
|
||||
|
||||
onUnmounted(() => {
|
||||
data.searchParams = null
|
||||
})
|
||||
|
||||
return {
|
||||
...toRefs(data),
|
||||
loadDataTable,
|
||||
handleModal
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style scoped lang='scss'>
|
||||
.n-button + .n-button {
|
||||
margin-left: 10px;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
import { ref, reactive } from 'vue'
|
||||
import { USER_STATUS } from '@/utils/dictionary.js'
|
||||
import { getDeptAll } from '@/api/system/dept/index'
|
||||
import { dataToSelect } from '@/utils/handleData.js'
|
||||
const departmentOptions = ref()
|
||||
|
||||
export const form = reactive({
|
||||
departmentForm: {
|
||||
code: '',
|
||||
name: '',
|
||||
sort: null,
|
||||
pid: null,
|
||||
note: ''
|
||||
},
|
||||
departmentRules: {
|
||||
code: [{ required: true, message: '请输入部门编号', trigger: 'blur' }],
|
||||
name: [{ required: true, message: '请输入部门名称', type: 'string', trigger: 'blur' }],
|
||||
sort: [{ required: true, type: 'number', message: '请输入排序号', trigger: 'blur' }]
|
||||
},
|
||||
formItem: [
|
||||
{ type: 'input', key: 'code', label: '部门编号', props: { maxlength: '20', placeholder: '请输入部门编号', clearable: true }},
|
||||
{ type: 'input', key: 'name', label: '部门名称', props: { maxlength: '20', placeholder: '请输入部门名称', clearable: true }},
|
||||
{ type: 'select', key: 'pid', label: '所属部门', props: { options: departmentOptions, placeholder: '请选择所属部门' }},
|
||||
{ type: 'number', key: 'sort', label: '排序号', props: { min: 0, placeholder: '请输入排序号', clearable: true }},
|
||||
{ type: 'input', key: 'note', label: '备注', props: { type: 'textarea', autosize: { maxlength: '200', minRows: 3, maxRows: 3 }}}
|
||||
]
|
||||
})
|
||||
|
||||
export const getDeptOptions = async function() {
|
||||
const res = await getDeptAll()
|
||||
departmentOptions.value = dataToSelect(res.data, { label: 'name', value: 'id' })
|
||||
}
|
||||
|
|
@ -1,4 +1,6 @@
|
|||
const data = [
|
||||
import { reactive } from 'vue'
|
||||
|
||||
const data = reactive([
|
||||
{
|
||||
label: '部门名称',
|
||||
key: 'name',
|
||||
|
|
@ -6,7 +8,7 @@ const data = [
|
|||
placeholder: '请输入部门名称'
|
||||
}
|
||||
}
|
||||
]
|
||||
])
|
||||
|
||||
export default data
|
||||
|
||||
|
|
@ -0,0 +1,124 @@
|
|||
import { h, ref, reactive } from 'vue'
|
||||
import TableAction from '@/components/DataTable/tools/Action.vue'
|
||||
import { deleteDept } from '@/api/system/dept/index.js'
|
||||
|
||||
/* 注册table */
|
||||
const tableRef = ref()
|
||||
const searchParams = ref()
|
||||
|
||||
function handleSearch(params) {
|
||||
searchParams.value = { ...params }
|
||||
tableRef.value.reFetch({ searchParams })
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: 获取数据及操作
|
||||
* @param {*} row 单行数据
|
||||
* @param {*} type 操作类型 create:创建,preview:预览,edit:编辑
|
||||
* @return {*}
|
||||
*/
|
||||
function getRowData(row, type) {
|
||||
data.rowData = type === 'create' ? { pid: row.id } : row
|
||||
data.modalType = type
|
||||
data.modalShow = true
|
||||
}
|
||||
|
||||
// 删除方法
|
||||
function deleteData(id) {
|
||||
deleteDept(id)
|
||||
.then((res) => {
|
||||
if (res.code === 0) {
|
||||
handleSearch()
|
||||
}
|
||||
})
|
||||
.catch((e) => {
|
||||
console.log(e)
|
||||
})
|
||||
}
|
||||
|
||||
const data = reactive({
|
||||
tableRef,
|
||||
searchParams,
|
||||
rowData: {},
|
||||
modalType: 'create',
|
||||
modalShow: false,
|
||||
handleSearch,
|
||||
|
||||
columns: [
|
||||
{
|
||||
title: '部门编号',
|
||||
key: 'code',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: '部门名称',
|
||||
key: 'name',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: '排序',
|
||||
key: 'sort',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: '创建时间',
|
||||
key: 'createTime',
|
||||
align: 'center',
|
||||
minWidth: 120
|
||||
},
|
||||
{
|
||||
title: '更新时间',
|
||||
key: 'updateTime',
|
||||
align: 'center',
|
||||
minWidth: 120
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
align: 'center',
|
||||
width: 150,
|
||||
fixed: 'right',
|
||||
render(row) {
|
||||
return h(TableAction, {
|
||||
actions: [
|
||||
{
|
||||
label: '添加',
|
||||
type: 'button',
|
||||
props: {
|
||||
type: 'primary',
|
||||
text: true,
|
||||
onClick: getRowData.bind(null, row, 'create')
|
||||
},
|
||||
auth: 'basic_list'
|
||||
},
|
||||
{
|
||||
label: '修改',
|
||||
type: 'button',
|
||||
props: {
|
||||
type: 'primary',
|
||||
text: true,
|
||||
onClick: getRowData.bind(null, row, 'update')
|
||||
},
|
||||
auth: 'basic_list'
|
||||
},
|
||||
{
|
||||
label: '删除',
|
||||
type: 'popconfirm',
|
||||
auth: 'basic_list',
|
||||
tip: '确定删除这条数据吗?',
|
||||
props: {
|
||||
onPositiveClick: deleteData.bind(null, [row.id])
|
||||
},
|
||||
ButtonProps: {
|
||||
text: true,
|
||||
type: 'primary'
|
||||
}
|
||||
}
|
||||
],
|
||||
align: 'center'
|
||||
})
|
||||
}
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
export default data
|
||||
|
|
@ -0,0 +1,161 @@
|
|||
<template>
|
||||
<Modal
|
||||
:options="getModalOptions"
|
||||
:on-close="handleClose"
|
||||
:on-positive-click="handleConfirm"
|
||||
:on-negative-click="handleClose"
|
||||
>
|
||||
<template #Context>
|
||||
<n-form
|
||||
ref="formRef"
|
||||
:model="menuForm"
|
||||
:rules="menuRules"
|
||||
:label-width="80"
|
||||
label-placement="left"
|
||||
require-mark-placement="left"
|
||||
:disabled="disabled"
|
||||
>
|
||||
<n-grid x-gap="12" :cols="2">
|
||||
<template v-for="(item,index) in getFormOptions" :key="index">
|
||||
<n-gi>
|
||||
<n-form-item :label="item.label" :path="item.key">
|
||||
<n-input v-if="item.type === 'input'" v-model:value="menuForm[item.key]" v-bind="item.props" />
|
||||
<n-select v-if="item.type === 'select'" v-model:value="menuForm[item.key]" v-bind="item.props" />
|
||||
<n-input-number v-if="item.type === 'number'" v-model:value="menuForm[item.key]" v-bind="item.props" />
|
||||
<n-radio-group v-if="item.type === 'radio'" v-model:value="menuForm[item.key]" :name="item.key">
|
||||
<n-space>
|
||||
<n-radio v-for="(cItem,cIndex) in item.options" :key="`${item.key}_${cIndex}`" :value="cItem.value"> {{ cItem.label }}</n-radio>
|
||||
</n-space>
|
||||
</n-radio-group>
|
||||
</n-form-item>
|
||||
</n-gi>
|
||||
</template>
|
||||
</n-grid>
|
||||
|
||||
</n-form>
|
||||
</template>
|
||||
</Modal>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { form, changeMenuType, getMenuOptions } from '../tools/form.js'
|
||||
import { defineComponent, ref, reactive, computed, watch, toRefs } from 'vue'
|
||||
import Modal from '@/components/Modal/index.vue'
|
||||
import { addMenu, editMenu } from '@/api/system/menu/index.js'
|
||||
export default defineComponent({
|
||||
name: 'MenuModal',
|
||||
components: { Modal },
|
||||
props: {
|
||||
visible: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
default: 'create'
|
||||
},
|
||||
data: {
|
||||
type: Object,
|
||||
default: () => {}
|
||||
}
|
||||
},
|
||||
emits: {
|
||||
'update:visible': null,
|
||||
'reload': null
|
||||
},
|
||||
setup(props, { emit }) {
|
||||
const MODAL_TYPE = {
|
||||
'create': '新建菜单',
|
||||
'preview': '菜单详情',
|
||||
'update': '编辑菜单'
|
||||
}
|
||||
getMenuOptions()
|
||||
const { menuForm, menuRules } = form
|
||||
const formRef = ref()
|
||||
const data = reactive({
|
||||
menuForm: {
|
||||
...menuForm,
|
||||
...props.data,
|
||||
pid: props.data?.pid === 0 ? null : props.data?.pid
|
||||
},
|
||||
menuRules: {
|
||||
...menuRules
|
||||
},
|
||||
disabled: props.type === 'preview'
|
||||
})
|
||||
|
||||
watch(() => data.menuForm.type,
|
||||
(val) => {
|
||||
switch (val) {
|
||||
case 0:
|
||||
data.menuForm.permission = ''
|
||||
break
|
||||
case 1:
|
||||
data.menuForm.path = ''
|
||||
data.menuForm.component = ''
|
||||
break
|
||||
}
|
||||
changeMenuType(val)
|
||||
})
|
||||
|
||||
const getModalOptions = computed(() => {
|
||||
return {
|
||||
title: MODAL_TYPE[props.type],
|
||||
show: props.visible,
|
||||
negativeText: '取消',
|
||||
positiveText: '确认'
|
||||
}
|
||||
})
|
||||
|
||||
const getFormOptions = computed(() => {
|
||||
console.log('change')
|
||||
return {
|
||||
...form.formItem
|
||||
}
|
||||
})
|
||||
|
||||
function handleConfirm() {
|
||||
formRef.value.validate((errors) => {
|
||||
if (!errors) {
|
||||
const params = { ...data.menuForm }
|
||||
if (params.id) {
|
||||
editMenu(params).then(res => {
|
||||
if (res.code === 0) {
|
||||
emit('reload')
|
||||
handleClose()
|
||||
}
|
||||
}).catch(e => {
|
||||
console.log(e)
|
||||
})
|
||||
} else {
|
||||
addMenu(params).then(res => {
|
||||
if (res.code === 0) {
|
||||
emit('reload')
|
||||
handleClose()
|
||||
}
|
||||
})
|
||||
}
|
||||
} else {
|
||||
$message.error('请完善必填信息')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/* 关闭弹窗 */
|
||||
const handleClose = () => {
|
||||
emit('update:visible', false)
|
||||
}
|
||||
|
||||
return {
|
||||
...toRefs(data),
|
||||
formRef,
|
||||
getModalOptions,
|
||||
getFormOptions,
|
||||
handleConfirm,
|
||||
handleClose
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
<style scoped lang='scss'>
|
||||
</style>
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
<template>
|
||||
<div>
|
||||
<n-card>
|
||||
<headSearch :info="search" @search="handleSearch" @reset="handleSearch" />
|
||||
<data-table
|
||||
ref="tableRef"
|
||||
:columns="columns"
|
||||
:pagination="false"
|
||||
data-type="tree"
|
||||
:request="loadDataTable"
|
||||
:row-key="(row) => row.id"
|
||||
>
|
||||
<template #tableTitle>
|
||||
<n-button type="primary" @click="handleModal"> 添加菜单 </n-button>
|
||||
</template>
|
||||
</data-table>
|
||||
</n-card>
|
||||
</div>
|
||||
|
||||
<MenuModal v-if="modalShow" v-model:visible="modalShow" :data="rowData" :type="modalType" @reload="handleSearch" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import search from './tools/search.js'
|
||||
import table from './tools/table.js'
|
||||
import headSearch from '@/components/Search/index.vue'
|
||||
import dataTable from '@/components/DataTable/index.vue'
|
||||
import MenuModal from './components/MenuModal.vue'
|
||||
import { getMenuList } from '@/api/system/menu/index.js'
|
||||
import { unref, reactive, toRefs, onUnmounted } from 'vue'
|
||||
|
||||
export default {
|
||||
name: 'MenuPage',
|
||||
components: { dataTable, MenuModal, headSearch },
|
||||
setup() {
|
||||
const data = reactive({
|
||||
...toRefs(table),
|
||||
search
|
||||
})
|
||||
|
||||
const loadDataTable = async(res) => {
|
||||
const _params = {
|
||||
...unref(data.searchParams),
|
||||
...res
|
||||
}
|
||||
return await getMenuList(_params)
|
||||
}
|
||||
|
||||
// 打开新增弹框
|
||||
function handleModal() {
|
||||
data.rowData = null
|
||||
data.modalType = 'create'
|
||||
data.modalShow = true
|
||||
}
|
||||
|
||||
onUnmounted(() => {
|
||||
data.searchParams = null
|
||||
})
|
||||
|
||||
return {
|
||||
...toRefs(data),
|
||||
loadDataTable,
|
||||
handleModal
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style scoped lang='scss'>
|
||||
</style>
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
import { ref, reactive, watch } from 'vue'
|
||||
import { MENU_TYPE, MENU_OPEN, MENU_VISIBLE, MENU_STATUS } from '@/utils/dictionary.js'
|
||||
import { getMenu } from '@/api/system/menu/index.js'
|
||||
import { dataToSelect } from '@/utils/handleData.js'
|
||||
const menuOptions = ref()
|
||||
const menuType0 = ref(true)
|
||||
const menuType1 = ref(false)
|
||||
|
||||
export const form = reactive({
|
||||
menuForm: {
|
||||
pid: null,
|
||||
type: 0,
|
||||
title: '',
|
||||
target: '1',
|
||||
icon: '',
|
||||
permission: '',
|
||||
path: '',
|
||||
sort: null,
|
||||
component: '',
|
||||
hide: 0,
|
||||
status: 1
|
||||
},
|
||||
menuRules: {
|
||||
title: [{ required: true, message: '请输入菜单名称', trigger: 'blur' }],
|
||||
sort: [{ required: true, type: 'number', message: '请输入排序号', trigger: 'blur' }]
|
||||
},
|
||||
formItem: [
|
||||
{ type: 'select', key: 'pid', label: '上级菜单', props: { options: menuOptions, placeholder: '请选择上级菜单' }},
|
||||
{ type: 'radio', key: 'type', label: '菜单类型', options: MENU_TYPE },
|
||||
{ type: 'input', key: 'title', label: '菜单名称', props: { maxlength: '20', placeholder: '请输入菜单名称', clearable: true }},
|
||||
{ type: 'radio', key: 'target', label: '打开方式', options: MENU_OPEN },
|
||||
{ type: 'input', key: 'icon', label: '菜单图标', props: { maxlength: '20', placeholder: '请选择菜单图标', clearable: true }},
|
||||
{ type: 'input', key: 'permission', label: '权限标识', props: { maxlength: '20', placeholder: '请输入部门名称', disabled: menuType0, clearable: true }},
|
||||
{ type: 'input', key: 'path', label: '路由地址', props: { maxlength: '20', placeholder: '请输入部门名称', disabled: menuType1, clearable: true }},
|
||||
{ type: 'number', key: 'sort', label: '排序号', props: { min: 0, placeholder: '请输入排序号', clearable: true }},
|
||||
{ type: 'input', key: 'component', label: '组件路径', props: { maxlength: '20', placeholder: '请输入部门名称', disabled: menuType1, clearable: true }},
|
||||
{ type: 'radio', key: 'hide', label: '是否可见', options: MENU_VISIBLE },
|
||||
{ type: 'radio', key: 'status', label: '菜单状态', options: MENU_STATUS }
|
||||
]
|
||||
})
|
||||
|
||||
export const getMenuOptions = async function() {
|
||||
const res = await getMenu()
|
||||
setTimeout(() => {
|
||||
menuOptions.value = dataToSelect(res.data, { label: 'title', value: 'id' })
|
||||
}, 3000)
|
||||
}
|
||||
|
||||
export const changeMenuType = function(value) {
|
||||
menuType0.value = !value
|
||||
menuType1.value = !menuType0.value
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
import { reactive } from 'vue'
|
||||
const data = reactive([
|
||||
{
|
||||
label: '菜单名称',
|
||||
key: 'title',
|
||||
props: {
|
||||
placeholder: '请输入菜单名称'
|
||||
}
|
||||
}
|
||||
])
|
||||
|
||||
export default data
|
||||
|
||||
|
|
@ -0,0 +1,165 @@
|
|||
import { MENU_TYPE, MENU_STATUS, MENU_VISIBLE } from '@/utils/dictionary.js'
|
||||
import { h, ref, reactive } from 'vue'
|
||||
import TableTags from '@/components/DataTable/tools/Tags.vue'
|
||||
import TableAction from '@/components/DataTable/tools/Action.vue'
|
||||
import { deleteMenu } from '@/api/system/menu/index.js'
|
||||
|
||||
/* 注册table */
|
||||
const tableRef = ref()
|
||||
const searchParams = ref()
|
||||
|
||||
function handleSearch(params) {
|
||||
searchParams.value = { ...params }
|
||||
tableRef.value.reFetch({ searchParams })
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: 获取数据及操作
|
||||
* @param {*} row 单行数据
|
||||
* @param {*} type 操作类型 create:创建,preview:预览,edit:编辑
|
||||
* @return {*}
|
||||
*/
|
||||
function getRowData(row, type) {
|
||||
data.rowData = type === 'create' ? { pid: row.id } : row
|
||||
data.modalType = type
|
||||
data.modalShow = true
|
||||
}
|
||||
|
||||
// 删除方法
|
||||
function deleteData(id) {
|
||||
deleteMenu(id)
|
||||
.then((res) => {
|
||||
if (res.code === 0) {
|
||||
handleSearch()
|
||||
}
|
||||
})
|
||||
.catch((e) => {
|
||||
console.log(e)
|
||||
})
|
||||
}
|
||||
|
||||
const data = reactive({
|
||||
tableRef,
|
||||
searchParams,
|
||||
rowData: {},
|
||||
modalType: 'create',
|
||||
modalShow: false,
|
||||
handleSearch,
|
||||
|
||||
columns: [
|
||||
{
|
||||
title: '菜单标题',
|
||||
key: 'title',
|
||||
align: 'center',
|
||||
width: 200
|
||||
},
|
||||
{
|
||||
title: '菜单类型',
|
||||
key: 'type',
|
||||
align: 'center',
|
||||
width: 100,
|
||||
render(row) {
|
||||
return h(TableTags, {
|
||||
data: row.type,
|
||||
filters: MENU_TYPE
|
||||
})
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '路由地址',
|
||||
key: 'path',
|
||||
align: 'center',
|
||||
width: 200
|
||||
},
|
||||
{
|
||||
title: '组件路径',
|
||||
key: 'component',
|
||||
align: 'center',
|
||||
width: 200
|
||||
},
|
||||
{
|
||||
title: '状态',
|
||||
key: 'status',
|
||||
align: 'center',
|
||||
width: 100,
|
||||
render(row) {
|
||||
return h(TableTags, {
|
||||
data: row.status,
|
||||
filters: MENU_STATUS
|
||||
})
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '排序',
|
||||
key: 'sort',
|
||||
align: 'center',
|
||||
width: 100
|
||||
},
|
||||
{
|
||||
title: '是否可见',
|
||||
key: 'hide',
|
||||
align: 'center',
|
||||
width: 100,
|
||||
render(row) {
|
||||
return h(TableTags, {
|
||||
data: row.hide,
|
||||
filters: MENU_VISIBLE
|
||||
})
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '创建时间',
|
||||
key: 'createTime',
|
||||
align: 'center',
|
||||
width: 160
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
align: 'center',
|
||||
width: 150,
|
||||
fixed: 'right',
|
||||
render(row) {
|
||||
return h(TableAction, {
|
||||
actions: [
|
||||
{
|
||||
label: '添加',
|
||||
type: 'button',
|
||||
props: {
|
||||
type: 'primary',
|
||||
text: true,
|
||||
onClick: getRowData.bind(null, row, 'create')
|
||||
},
|
||||
auth: 'basic_list'
|
||||
},
|
||||
{
|
||||
label: '修改',
|
||||
type: 'button',
|
||||
props: {
|
||||
type: 'primary',
|
||||
text: true,
|
||||
onClick: getRowData.bind(null, row, 'update')
|
||||
},
|
||||
auth: 'basic_list'
|
||||
},
|
||||
{
|
||||
label: '删除',
|
||||
type: 'popconfirm',
|
||||
auth: 'basic_list',
|
||||
tip: '确定删除这条数据吗?',
|
||||
props: {
|
||||
onPositiveClick: deleteData.bind(null, [row.id])
|
||||
},
|
||||
ButtonProps: {
|
||||
text: true,
|
||||
type: 'primary'
|
||||
}
|
||||
}
|
||||
],
|
||||
align: 'center'
|
||||
})
|
||||
}
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
export default data
|
||||
|
|
@ -33,14 +33,14 @@ export default defineComponent({
|
|||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
row: {
|
||||
data: {
|
||||
type: Object,
|
||||
default: () => {}
|
||||
}
|
||||
},
|
||||
emits: {
|
||||
'update:visible': null,
|
||||
'done': null
|
||||
'reload': null
|
||||
},
|
||||
setup(props, { emit }) {
|
||||
const data = reactive({
|
||||
|
|
@ -62,7 +62,7 @@ export default defineComponent({
|
|||
|
||||
// 获取当前角色的权限菜单列表
|
||||
async function getMenuByRoleId() {
|
||||
const res = await getRolePermission(props.row.id)
|
||||
const res = await getRolePermission(props.data.id)
|
||||
data.allTreeData = toTreeData(res.data, 'id', 'pid', 'children')
|
||||
const checkedArr = res.data
|
||||
if (checkedArr.length) {
|
||||
|
|
@ -80,6 +80,17 @@ export default defineComponent({
|
|||
data.menuIds = keys
|
||||
}
|
||||
|
||||
function handleConfirm() {
|
||||
savePermission({ roleId: props.data.id, menuIds: data.menuIds }).then(res => {
|
||||
if (res.code === 0) {
|
||||
emit('reload')
|
||||
handleClose()
|
||||
}
|
||||
}).catch(e => {
|
||||
console.log(e)
|
||||
})
|
||||
}
|
||||
|
||||
/* 关闭弹窗 */
|
||||
const handleClose = () => {
|
||||
emit('update:visible', false)
|
||||
|
|
@ -88,25 +99,9 @@ export default defineComponent({
|
|||
return {
|
||||
...toRefs(data),
|
||||
getModalOptions,
|
||||
handleClose,
|
||||
handleCheckTree
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 提交
|
||||
handleConfirm() {
|
||||
console.log(this.menuIds, this.checkedTreeData)
|
||||
savePermission({ roleId: this.row.id, menuIds: this.menuIds }).then(res => {
|
||||
if (res.code === 0) {
|
||||
this.handleClose()
|
||||
this.$emit('done')
|
||||
$message.success(res.msg)
|
||||
} else {
|
||||
$message.error(res.msg)
|
||||
}
|
||||
}).catch(e => {
|
||||
console.log(e)
|
||||
})
|
||||
handleCheckTree,
|
||||
handleConfirm,
|
||||
handleClose
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
@ -0,0 +1,139 @@
|
|||
<template>
|
||||
<Modal
|
||||
:options="getModalOptions"
|
||||
:on-positive-click="handleConfirm"
|
||||
:on-negative-click="handleClose"
|
||||
:on-close="handleClose"
|
||||
>
|
||||
<template #Context>
|
||||
<n-form
|
||||
ref="formRef"
|
||||
:model="roleForm"
|
||||
:rules="roleRules"
|
||||
:label-width="80"
|
||||
label-placement="left"
|
||||
require-mark-placement="left"
|
||||
:disabled="disabled"
|
||||
>
|
||||
<template v-for="(item,index) in getFormOptions" :key="index">
|
||||
<n-form-item :label="item.label" :path="item.key">
|
||||
<n-input v-if="item.type === 'input'" v-model:value="roleForm[item.key]" v-bind="item.props" />
|
||||
<n-radio-group v-if="item.type === 'radio'" v-model:value="roleForm[item.key]" :name="item.key">
|
||||
<n-space>
|
||||
<n-radio v-for="(cItem,cIndex) in item.options" :key="`${item.key}_${cIndex}`" :value="cItem.value"> {{ cItem.label }}</n-radio>
|
||||
</n-space>
|
||||
</n-radio-group>
|
||||
</n-form-item>
|
||||
</template>
|
||||
</n-form>
|
||||
</template>
|
||||
</Modal>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import form from '../tools/form.js'
|
||||
import { defineComponent, ref, reactive, computed, toRefs } from 'vue'
|
||||
import Modal from '@/components/Modal/index.vue'
|
||||
import { addRole, editRole } from '@/api/system/role/index'
|
||||
export default defineComponent({
|
||||
name: 'RoleModal',
|
||||
components: { Modal },
|
||||
props: {
|
||||
visible: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
default: 'create'
|
||||
},
|
||||
data: {
|
||||
type: Object,
|
||||
default: () => {}
|
||||
}
|
||||
},
|
||||
emits: {
|
||||
'update:visible': null,
|
||||
'reload': null
|
||||
},
|
||||
setup(props, { emit }) {
|
||||
const MODAL_TYPE = {
|
||||
'create': '新建角色',
|
||||
'preview': '角色详情',
|
||||
'update': '编辑角色'
|
||||
}
|
||||
const { roleForm, roleRules } = form
|
||||
const formRef = ref()
|
||||
const data = reactive({
|
||||
roleForm: {
|
||||
...roleForm,
|
||||
...props.data
|
||||
},
|
||||
roleRules: {
|
||||
...roleRules
|
||||
},
|
||||
disabled: props.type === 'preview'
|
||||
})
|
||||
|
||||
const getModalOptions = computed(() => {
|
||||
return {
|
||||
title: MODAL_TYPE[props.type],
|
||||
show: props.visible,
|
||||
negativeText: '取消',
|
||||
positiveText: '确认'
|
||||
}
|
||||
})
|
||||
|
||||
const getFormOptions = computed(() => {
|
||||
return {
|
||||
...form.formItem
|
||||
}
|
||||
})
|
||||
|
||||
function handleConfirm() {
|
||||
formRef.value?.validate((errors) => {
|
||||
if (!errors) {
|
||||
const params = { ...data.roleForm }
|
||||
if (params.id) {
|
||||
/* 编辑 */
|
||||
editRole(params)
|
||||
.then(res => {
|
||||
if (res.code === 0) {
|
||||
emit('reload')
|
||||
handleClose()
|
||||
}
|
||||
})
|
||||
} else {
|
||||
/* 新增 */
|
||||
addRole(params)
|
||||
.then(res => {
|
||||
if (res.code === 0) {
|
||||
emit('reload')
|
||||
handleClose()
|
||||
}
|
||||
})
|
||||
}
|
||||
} else {
|
||||
$message.error('请完善必填信息')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/* 关闭弹窗 */
|
||||
const handleClose = () => {
|
||||
emit('update:visible', false)
|
||||
}
|
||||
|
||||
return {
|
||||
...toRefs(data),
|
||||
formRef,
|
||||
getModalOptions,
|
||||
getFormOptions,
|
||||
handleConfirm,
|
||||
handleClose
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
<style scoped lang='scss'>
|
||||
</style>
|
||||
|
|
@ -0,0 +1,104 @@
|
|||
<template>
|
||||
<div>
|
||||
<n-card>
|
||||
<headSearch :info="search" @search="handleSearch" @reset="handleSearch" />
|
||||
<data-table
|
||||
ref="tableRef"
|
||||
:columns="columns"
|
||||
:row-key="(row) => row.id"
|
||||
:request="loadDataTable"
|
||||
size="large"
|
||||
scroll-x="1200"
|
||||
@update:checked-row-keys="handleCheck"
|
||||
>
|
||||
<template #tableTitle>
|
||||
<n-button type="primary" @click="handleModal"> 新建 </n-button>
|
||||
<n-popconfirm
|
||||
negative-text="取消"
|
||||
positive-text="确认"
|
||||
@positive-click="deleteComplex"
|
||||
>
|
||||
<template #trigger>
|
||||
<n-button type="primary">删除</n-button>
|
||||
</template>
|
||||
确定删除选中的数据吗?
|
||||
</n-popconfirm>
|
||||
</template>
|
||||
</data-table>
|
||||
</n-card>
|
||||
</div>
|
||||
<!-- 新增、编辑弹窗 -->
|
||||
<RoleModal v-if="modalShow" v-model:visible="modalShow" :data="rowData" :type="modalType" @reload="handleSearch" />
|
||||
<!-- 分配权限 -->
|
||||
<ConfigModal v-if="configModalShow" v-model:visible="configModalShow" :data="rowData" @reload="handleSearch" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import search from './tools/search.js'
|
||||
import table from './tools/table.js'
|
||||
import headSearch from '@/components/Search/index.vue'
|
||||
import dataTable from '@/components/DataTable/index.vue'
|
||||
import RoleModal from './components/RoleModal.vue'
|
||||
import ConfigModal from './components/ConfigModal.vue'
|
||||
import { getRoleList } from '@/api/system/role/index'
|
||||
import { ref, unref, toRefs, reactive, onUnmounted } from 'vue'
|
||||
|
||||
export default {
|
||||
name: 'MenuPage',
|
||||
components: { headSearch, dataTable, RoleModal, ConfigModal },
|
||||
setup() {
|
||||
const data = reactive({
|
||||
...toRefs(table),
|
||||
search
|
||||
})
|
||||
|
||||
const loadDataTable = async(res) => {
|
||||
const _params = {
|
||||
...unref(data.searchParams),
|
||||
...res
|
||||
}
|
||||
return await getRoleList(_params)
|
||||
}
|
||||
|
||||
// 新增用户
|
||||
function handleModal() {
|
||||
data.rowData = null
|
||||
data.modalType = 'create'
|
||||
data.modalShow = true
|
||||
}
|
||||
|
||||
// 选择表格数据
|
||||
const selectedIds = ref([])
|
||||
function handleCheck(rowKeys) {
|
||||
selectedIds.value = rowKeys
|
||||
}
|
||||
|
||||
// 批量删除
|
||||
function deleteComplex() {
|
||||
if (selectedIds.value.length) {
|
||||
data.deleteData(selectedIds.value)
|
||||
} else {
|
||||
$message.warning('请至少选中一条数据')
|
||||
}
|
||||
}
|
||||
|
||||
onUnmounted(() => {
|
||||
data.searchParams = null
|
||||
})
|
||||
|
||||
return {
|
||||
...toRefs(data),
|
||||
loadDataTable,
|
||||
handleModal,
|
||||
handleCheck,
|
||||
selectedIds,
|
||||
deleteComplex
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style scoped lang='scss'>
|
||||
.n-button + .n-button {
|
||||
margin-left: 10px;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
import { reactive } from 'vue'
|
||||
import { USER_STATUS } from '@/utils/dictionary.js'
|
||||
|
||||
const data = reactive({
|
||||
roleForm: {
|
||||
code: '',
|
||||
name: '',
|
||||
status: 1,
|
||||
note: ''
|
||||
},
|
||||
roleRules: {
|
||||
code: [{ required: true, message: '请输入角色编号', trigger: 'blur' }],
|
||||
name: [{ required: true, message: '请输入角色名称', type: 'string', trigger: 'blur' }],
|
||||
status: [{ required: true, message: '请选择状态', type: 'number', trigger: 'blur' }]
|
||||
},
|
||||
formItem: [
|
||||
{ type: 'input', key: 'code', label: '角色编号', props: { maxlength: '20', placeholder: '请输入角色编号', clearable: true }},
|
||||
{ type: 'input', key: 'name', label: '角色名称', props: { maxlength: '20', placeholder: '请输入角色名称', clearable: true }},
|
||||
{ type: 'radio', key: 'status', label: '状态', options: USER_STATUS },
|
||||
{ type: 'input', key: 'note', label: '备注', props: { type: 'textarea', autosize: { maxlength: '200', minRows: 3, maxRows: 3 }}}
|
||||
]
|
||||
})
|
||||
|
||||
export default data
|
||||
|
|
@ -1,4 +1,6 @@
|
|||
const data = [
|
||||
import { reactive } from 'vue'
|
||||
|
||||
const data = reactive([
|
||||
{
|
||||
label: '角色名称',
|
||||
key: 'name',
|
||||
|
|
@ -6,6 +8,6 @@ const data = [
|
|||
placeholder: '请输入角色名称'
|
||||
}
|
||||
}
|
||||
]
|
||||
])
|
||||
|
||||
export default data
|
||||
|
|
@ -0,0 +1,165 @@
|
|||
import { h, ref, reactive } from 'vue'
|
||||
import TableSwitch from '@/components/DataTable/tools/Switch.vue'
|
||||
import TableAction from '@/components/DataTable/tools/Action.vue'
|
||||
import { deleteRole, setRoleStatus } from '@/api/system/role/index'
|
||||
|
||||
/* 注册table */
|
||||
const tableRef = ref()
|
||||
const searchParams = ref()
|
||||
|
||||
function handleSearch(params) {
|
||||
searchParams.value = { ...params }
|
||||
tableRef.value.reFetch({ searchParams })
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: 获取数据及操作
|
||||
* @param {*} row 单行数据
|
||||
* @param {*} type 操作类型 create:创建,preview:预览,edit:编辑
|
||||
* @return {*}
|
||||
*/
|
||||
function getRowData(row, type) {
|
||||
data.rowData = row
|
||||
data.modalType = type
|
||||
data.modalShow = true
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: 打开分配权限窗口
|
||||
* @param {*} row 单行数据
|
||||
* @return {*}
|
||||
*/
|
||||
function configure(row) {
|
||||
data.rowData = row
|
||||
data.configModalShow = true
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: 改变状态
|
||||
* @param {*} row 选中数据
|
||||
* @return {*}
|
||||
*/
|
||||
function handleStatusChange(row) {
|
||||
setRoleStatus({ id: row.data.id, status: row.value })
|
||||
.then((res) => {
|
||||
if (res.code === 0) {
|
||||
handleSearch()
|
||||
}
|
||||
})
|
||||
.catch((e) => {
|
||||
console.log(e)
|
||||
})
|
||||
}
|
||||
|
||||
// 删除接口
|
||||
function deleteData(data) {
|
||||
deleteRole(data)
|
||||
.then((res) => {
|
||||
if (res.code === 0) {
|
||||
handleSearch()
|
||||
}
|
||||
})
|
||||
.catch((e) => {
|
||||
console.log(e)
|
||||
})
|
||||
}
|
||||
|
||||
const data = reactive({
|
||||
tableRef,
|
||||
searchParams,
|
||||
rowData: {},
|
||||
modalType: 'create',
|
||||
modalShow: false,
|
||||
configModalShow: false,
|
||||
handleSearch,
|
||||
deleteData,
|
||||
columns: [
|
||||
{ type: 'selection' },
|
||||
{
|
||||
title: '角色编号',
|
||||
key: 'code',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: '角色名称',
|
||||
key: 'name',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: '创建时间',
|
||||
key: 'createTime',
|
||||
align: 'center',
|
||||
Minwidth: 160
|
||||
},
|
||||
{
|
||||
title: '更新时间',
|
||||
key: 'updateTime',
|
||||
align: 'center',
|
||||
Minwidth: 160
|
||||
},
|
||||
{
|
||||
title: '状态',
|
||||
key: 'status',
|
||||
align: 'center',
|
||||
width: 100,
|
||||
render(row) {
|
||||
return h(TableSwitch, {
|
||||
data: { id: row.id, status: row.status },
|
||||
rowKey: 'status',
|
||||
checkedValue: 1,
|
||||
uncheckedValue: 2,
|
||||
onChange: handleStatusChange.bind(row)
|
||||
})
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
align: 'center',
|
||||
width: 150,
|
||||
fixed: 'right',
|
||||
render(row) {
|
||||
return h(TableAction, {
|
||||
actions: [
|
||||
{
|
||||
label: '修改',
|
||||
type: 'button',
|
||||
props: {
|
||||
type: 'primary',
|
||||
text: true,
|
||||
onClick: getRowData.bind(null, row, 'update')
|
||||
},
|
||||
auth: 'basic_list'
|
||||
},
|
||||
{
|
||||
label: '分配权限',
|
||||
type: 'button',
|
||||
props: {
|
||||
type: 'primary',
|
||||
ghost: true,
|
||||
text: true,
|
||||
onClick: configure.bind(null, row)
|
||||
},
|
||||
auth: 'basic_list'
|
||||
},
|
||||
{
|
||||
label: '删除',
|
||||
type: 'popconfirm',
|
||||
auth: 'basic_list',
|
||||
tip: '确定删除这条数据吗?',
|
||||
props: {
|
||||
onPositiveClick: deleteData.bind(null, [row.id])
|
||||
},
|
||||
ButtonProps: {
|
||||
text: true,
|
||||
type: 'primary'
|
||||
}
|
||||
}
|
||||
],
|
||||
align: 'center'
|
||||
})
|
||||
}
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
export default data
|
||||
|
|
@ -0,0 +1,168 @@
|
|||
<template>
|
||||
<Modal
|
||||
:options="getModalOptions"
|
||||
:on-positive-click="handleConfirm"
|
||||
:on-negative-click="handleClose"
|
||||
:on-close="handleClose"
|
||||
>
|
||||
<template #Context>
|
||||
<n-form
|
||||
ref="formRef"
|
||||
:model="userForm"
|
||||
:rules="userRules"
|
||||
:label-width="80"
|
||||
label-placement="left"
|
||||
require-mark-placement="left"
|
||||
:disabled="disabled"
|
||||
>
|
||||
<template v-for="(item,index) in getFormOptions" :key="index">
|
||||
<n-form-item :label="item.label" :path="item.key">
|
||||
<UploadOss v-if="item.type === 'oss'" :ref="el=>{ossRefs[item.refIndex] = el}" :default-list="userForm[item.file]" @upload-status="handleUploadStatus" />
|
||||
<n-input v-if="item.type === 'input'" v-model:value="userForm[item.key]" v-bind="item.props" />
|
||||
<n-select v-if="item.type === 'select'" v-model:value="userForm[item.key]" v-bind="item.props" />
|
||||
<n-radio-group v-if="item.type === 'radio'" v-model:value="userForm[item.key]" :name="item.key">
|
||||
<n-space>
|
||||
<n-radio v-for="(cItem,cIndex) in item.options" :key="`${item.key}_${cIndex}`" :value="cItem.value"> {{ cItem.label }}</n-radio>
|
||||
</n-space>
|
||||
</n-radio-group>
|
||||
</n-form-item>
|
||||
</template>
|
||||
</n-form>
|
||||
</template>
|
||||
</Modal>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { form, getDeptOptions, getRoleOptions } from '../tools/form.js'
|
||||
import { defineComponent, ref, reactive, computed, toRefs } from 'vue'
|
||||
import Modal from '@/components/Modal/index.vue'
|
||||
import UploadOss from '@/components/UploadOss/index.vue'
|
||||
import { addUser, editUser } from '@/api/system/user/index'
|
||||
export default defineComponent({
|
||||
name: 'UserModal',
|
||||
components: { Modal, UploadOss },
|
||||
props: {
|
||||
visible: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
default: 'create'
|
||||
},
|
||||
data: {
|
||||
type: Object,
|
||||
default: () => null
|
||||
}
|
||||
},
|
||||
emits: {
|
||||
'update:visible': null,
|
||||
'reload': null
|
||||
},
|
||||
setup(props, { emit }) {
|
||||
const MODAL_TYPE = {
|
||||
'create': '新建用户',
|
||||
'preview': '用户详情',
|
||||
'update': '编辑用户'
|
||||
}
|
||||
getDeptOptions()
|
||||
getRoleOptions()
|
||||
const { userForm, userRules } = form
|
||||
const formRef = ref()
|
||||
const ossRefs = ref([])
|
||||
const data = reactive({
|
||||
userForm: {
|
||||
...userForm,
|
||||
...props.data,
|
||||
roleIds: props?.data?.roles.map((item) => { return item.id }) || []
|
||||
},
|
||||
userRules: {
|
||||
...userRules
|
||||
},
|
||||
disabled: props.type === 'preview'
|
||||
})
|
||||
const getModalOptions = computed(() => {
|
||||
return {
|
||||
show: props.visible,
|
||||
title: MODAL_TYPE[props.type],
|
||||
negativeText: '取消',
|
||||
positiveText: '确认'
|
||||
}
|
||||
})
|
||||
|
||||
const getFormOptions = computed(() => {
|
||||
return {
|
||||
...form.formItem
|
||||
}
|
||||
})
|
||||
|
||||
function handleUploadStatus(status) {
|
||||
data.userForm.imageStatus = status
|
||||
}
|
||||
|
||||
function handleConfirm() {
|
||||
formRef.value?.validate((errors) => {
|
||||
if (!errors) {
|
||||
const uploads = ossRefs.value.map((item, index) => {
|
||||
return item.startUpload()
|
||||
})
|
||||
Promise.all(uploads)
|
||||
.then(response => {
|
||||
const isError = response.map((item) => {
|
||||
return item.includes('error')
|
||||
})
|
||||
if (!isError.includes(true)) {
|
||||
const imageStr = response.join()
|
||||
const params = {
|
||||
...data.userForm,
|
||||
// avatar: imageStr
|
||||
avatar: '/imagedir/2uim2hpl94u_1655380018696.png'
|
||||
}
|
||||
if (params.id) {
|
||||
/* 编辑 */
|
||||
editUser(params)
|
||||
.then(res => {
|
||||
if (res.code === 0) {
|
||||
emit('reload')
|
||||
handleClose()
|
||||
}
|
||||
})
|
||||
} else {
|
||||
/* 新增 */
|
||||
addUser(params)
|
||||
.then(res => {
|
||||
if (res.code === 0) {
|
||||
emit('reload')
|
||||
handleClose()
|
||||
}
|
||||
})
|
||||
}
|
||||
} else {
|
||||
$message.error('文件上传失败,请稍后重试')
|
||||
}
|
||||
})
|
||||
} else {
|
||||
$message.error('请完善必填信息')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/* 关闭弹窗 */
|
||||
const handleClose = () => {
|
||||
emit('update:visible', false)
|
||||
}
|
||||
return {
|
||||
...toRefs(data),
|
||||
formRef,
|
||||
ossRefs,
|
||||
getModalOptions,
|
||||
getFormOptions,
|
||||
handleUploadStatus,
|
||||
handleConfirm,
|
||||
handleClose
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
<style scoped lang='scss'>
|
||||
</style>
|
||||
|
|
@ -0,0 +1,105 @@
|
|||
<template>
|
||||
<div>
|
||||
<n-card>
|
||||
<headSearch :info="search" @search="handleSearch" @reset="handleSearch" />
|
||||
<data-table
|
||||
ref="tableRef"
|
||||
:columns="columns"
|
||||
:row-key="(row) => row.id"
|
||||
:request="loadDataTable"
|
||||
size="large"
|
||||
@update:checked-row-keys="handleCheck"
|
||||
>
|
||||
<template #tableTitle>
|
||||
<n-button type="primary" @click="handleModal"> 新建 </n-button>
|
||||
<n-popconfirm
|
||||
negative-text="取消"
|
||||
positive-text="确认"
|
||||
@positive-click="deleteComplex"
|
||||
>
|
||||
<template #trigger>
|
||||
<n-button type="primary"> 删除 </n-button>
|
||||
</template>
|
||||
确认要删除选中数据吗?
|
||||
</n-popconfirm>
|
||||
</template>
|
||||
</data-table>
|
||||
</n-card>
|
||||
</div>
|
||||
|
||||
<!-- 新增、编辑弹窗 -->
|
||||
<UserModal v-if="modalShow" v-model:visible="modalShow" :type="modalType" :data="rowData" @reload="handleSearch" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { search, fetchRolesOption } from './tools/search.js'
|
||||
import table from './tools/table.js'
|
||||
import headSearch from '@/components/Search/index.vue'
|
||||
import dataTable from '@/components/DataTable/index.vue'
|
||||
import UserModal from './components/UserModal.vue'
|
||||
import { getUserList } from '@/api/system/user/index.js'
|
||||
import { unref, ref, toRefs, reactive, onUnmounted } from 'vue'
|
||||
|
||||
export default {
|
||||
name: 'MenuPage',
|
||||
components: { dataTable, UserModal, headSearch },
|
||||
setup() {
|
||||
fetchRolesOption()
|
||||
const data = reactive({
|
||||
...toRefs(table),
|
||||
...toRefs(search)
|
||||
})
|
||||
|
||||
const loadDataTable = async(res) => {
|
||||
const _params = {
|
||||
...unref(data.searchParams),
|
||||
...res
|
||||
}
|
||||
return await getUserList(_params)
|
||||
}
|
||||
|
||||
// 新增
|
||||
function handleModal() {
|
||||
data.rowData = null
|
||||
data.modalType = 'create'
|
||||
data.modalShow = true
|
||||
}
|
||||
|
||||
// 选择表格数据
|
||||
const selectedIds = ref([])
|
||||
function handleCheck(rowKeys) {
|
||||
selectedIds.value = rowKeys
|
||||
}
|
||||
|
||||
// 批量删除
|
||||
function deleteComplex() {
|
||||
if (selectedIds.value.length) {
|
||||
data.deleteData(selectedIds.value)
|
||||
} else {
|
||||
$message.warning('请至少选中一条数据')
|
||||
}
|
||||
}
|
||||
|
||||
onUnmounted(() => {
|
||||
data.searchParams = null
|
||||
})
|
||||
|
||||
return {
|
||||
...toRefs(data),
|
||||
loadDataTable,
|
||||
handleModal,
|
||||
selectedIds,
|
||||
deleteComplex,
|
||||
handleCheck
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style scoped lang='scss'>
|
||||
.n-button + .n-button {
|
||||
margin-left: 10px;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
import { ref, reactive } from 'vue'
|
||||
import { USER_STATUS } from '@/utils/dictionary.js'
|
||||
import { getDeptAll } from '@/api/system/dept/index'
|
||||
import { getRoleAll } from '@/api/system/role/index'
|
||||
import { dataToSelect } from '@/utils/handleData.js'
|
||||
const departmentOptions = ref()
|
||||
const rolesOptions = ref()
|
||||
export const form = reactive({
|
||||
userForm: {
|
||||
avatar: '',
|
||||
code: '',
|
||||
deptId: null,
|
||||
username: '',
|
||||
realname: '',
|
||||
password: '',
|
||||
roleIds: [],
|
||||
status: 1,
|
||||
note: ''
|
||||
},
|
||||
userRules: {
|
||||
imageStatus: [{ required: true, message: '请选择头像', type: 'string', trigger: 'blur' }],
|
||||
code: [{ required: true, message: '请输入编号', trigger: 'blur' }],
|
||||
realname: [{ required: true, message: '请输入用户姓名', type: 'string', trigger: 'blur' }],
|
||||
deptId: [{ required: true, message: '请选择部门', type: 'number', trigger: 'blur' }],
|
||||
status: [{ required: true, message: '请选择状态', type: 'number', trigger: 'blur' }],
|
||||
roleIds: [{ required: true, message: '请选择角色', type: 'array', trigger: 'blur' }],
|
||||
username: [{ required: true, message: '请输入用户账号', type: 'string', trigger: 'blur' }]
|
||||
},
|
||||
formItem: [
|
||||
// { type: 'oss', key: 'imageStatus', label: '头像', file: 'avatar', refIndex: 0 },
|
||||
{ type: 'oss', key: 'imageStatus', label: '头像', file: 'avatar' },
|
||||
{ type: 'input', key: 'code', label: '用户编号', props: { maxlength: '20', placeholder: '请输入用户编号', clearable: true }},
|
||||
{ type: 'input', key: 'username', label: '用户账号', props: { maxlength: '20', placeholder: '请输入用户账号', clearable: true }},
|
||||
{ type: 'input', key: 'password', label: '登录密码', props: { type: 'password', maxlength: '20', placeholder: '请输入登录密码', clearable: true }},
|
||||
{ type: 'input', key: 'realname', label: '用户姓名', props: { maxlength: '20', placeholder: '请输入用户姓名', clearable: true }},
|
||||
{ type: 'select', key: 'deptId', label: '所属部门', props: { options: departmentOptions, placeholder: '请选择所属部门' }},
|
||||
{ type: 'select', key: 'roleIds', label: '角色', props: { multiple: true, options: rolesOptions, placeholder: '请选择角色' }},
|
||||
{ type: 'radio', key: 'status', label: '状态', options: USER_STATUS },
|
||||
{ type: 'input', key: 'note', label: '备注', props: { type: 'textarea', autosize: { maxlength: '200', minRows: 3, maxRows: 3 }}}
|
||||
]
|
||||
})
|
||||
|
||||
export const getDeptOptions = async function() {
|
||||
const res = await getDeptAll()
|
||||
departmentOptions.value = dataToSelect(res.data, { label: 'name', value: 'id' })
|
||||
}
|
||||
|
||||
// 获取角色列表
|
||||
export const getRoleOptions = async function() {
|
||||
const res = await getRoleAll()
|
||||
rolesOptions.value = dataToSelect(res.data, { label: 'name', value: 'id' })
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
import { getRoleAll } from '@/api/system/role/index'
|
||||
import { ref, reactive } from 'vue'
|
||||
const rolesOptions = ref([])
|
||||
|
||||
export const search = reactive({
|
||||
search: [
|
||||
{
|
||||
label: '用户账号',
|
||||
key: 'username',
|
||||
props: {
|
||||
placeholder: '请输入用户账号'
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '用户姓名',
|
||||
key: 'realname',
|
||||
props: {
|
||||
placeholder: '请输入用户姓名'
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '用户角色',
|
||||
type: 'select',
|
||||
key: 'roleId',
|
||||
props: {
|
||||
placeholder: '请选择用户角色',
|
||||
options: rolesOptions
|
||||
}
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
export const fetchRolesOption = async function() {
|
||||
const res = await getRoleAll()
|
||||
rolesOptions.value = res.data.map((item) => { return { key: item.id, label: item.name } })
|
||||
}
|
||||
|
|
@ -0,0 +1,210 @@
|
|||
import { h, ref, reactive } from 'vue'
|
||||
import TableImage from '@/components/DataTable/tools/Image.vue'
|
||||
import TableTags from '@/components/DataTable/tools/Tags.vue'
|
||||
import TableSwitch from '@/components/DataTable/tools/Switch.vue'
|
||||
import TableAction from '@/components/DataTable/tools/Action.vue'
|
||||
import { resetPassword, deleteUser, setUserStatus } from '@/api/system/user/index.js'
|
||||
|
||||
/* 注册table */
|
||||
const tableRef = ref()
|
||||
const searchParams = ref()
|
||||
|
||||
function handleSearch(params) {
|
||||
searchParams.value = { ...params }
|
||||
tableRef.value.reFetch({ searchParams })
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: 获取数据及操作
|
||||
* @param {*} row 单行数据
|
||||
* @param {*} type 操作类型 create:创建,preview:预览,edit:编辑
|
||||
* @return {*}
|
||||
*/
|
||||
function getRowData(row, type) {
|
||||
data.rowData = row
|
||||
data.modalType = type
|
||||
data.modalShow = true
|
||||
}
|
||||
|
||||
// 设置状态
|
||||
function setStatus(row) {
|
||||
setUserStatus({ id: row.data.id, status: row.value }).then(res => {
|
||||
if (res.code === 0) {
|
||||
handleSearch()
|
||||
$message.success(res.msg)
|
||||
} else {
|
||||
$message.error(res.msg)
|
||||
}
|
||||
}).catch(e => {
|
||||
console.log(e)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: 重置密码
|
||||
* @param {Number} id 选中数据id
|
||||
* @return {*}
|
||||
*/
|
||||
function handlePasswordReset(id) {
|
||||
resetPassword({ id })
|
||||
.then(res => {
|
||||
if (res.code === 0) {
|
||||
handleSearch()
|
||||
}
|
||||
}).catch(e => {
|
||||
console.log(e)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: 删除用户接口
|
||||
* @param {Array} ids 用户id集合
|
||||
* @return {*}
|
||||
*/
|
||||
function deleteData(ids) {
|
||||
deleteUser(ids).then((res) => {
|
||||
if (res.code === 0) {
|
||||
handleSearch()
|
||||
}
|
||||
}).catch(e => {
|
||||
console.log(e)
|
||||
})
|
||||
}
|
||||
|
||||
const data = reactive({
|
||||
tableRef,
|
||||
searchParams,
|
||||
rowData: {},
|
||||
modalType: 'create',
|
||||
modalShow: false,
|
||||
handleSearch,
|
||||
deleteData,
|
||||
columns: [
|
||||
{
|
||||
type: 'selection'
|
||||
},
|
||||
{
|
||||
title: '用户编号',
|
||||
key: 'code',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: '头像',
|
||||
key: 'avatar',
|
||||
align: 'center',
|
||||
render(row) {
|
||||
return h(TableImage, {
|
||||
images: {
|
||||
width: 36,
|
||||
height: 36,
|
||||
src: row.avatar
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '用户账号',
|
||||
key: 'username',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: '用户姓名',
|
||||
key: 'realname',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: '角色',
|
||||
key: 'roleList',
|
||||
align: 'center',
|
||||
render(row) {
|
||||
return h(TableTags, {
|
||||
data: row.roles,
|
||||
rowKey: 'name'
|
||||
})
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '部门',
|
||||
key: 'deptName',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: '创建时间',
|
||||
key: 'createTime',
|
||||
align: 'center',
|
||||
width: 160
|
||||
},
|
||||
{
|
||||
title: '更新时间',
|
||||
key: 'updateTime',
|
||||
align: 'center',
|
||||
width: 160
|
||||
},
|
||||
{
|
||||
title: '状态',
|
||||
key: 'status',
|
||||
align: 'center',
|
||||
width: 100,
|
||||
render(row) {
|
||||
return h(TableSwitch, {
|
||||
data: { id: row.id, status: row.status },
|
||||
rowKey: 'status',
|
||||
checkedValue: 1,
|
||||
uncheckedValue: 2,
|
||||
onChange: setStatus.bind(row)
|
||||
})
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
align: 'center',
|
||||
width: 150,
|
||||
fixed: 'right',
|
||||
render(row) {
|
||||
return h(TableAction, {
|
||||
actions: [
|
||||
{
|
||||
label: '修改',
|
||||
type: 'button',
|
||||
props: {
|
||||
type: 'primary',
|
||||
text: true,
|
||||
onClick: getRowData.bind(null, row, 'update')
|
||||
},
|
||||
auth: 'basic_list'
|
||||
},
|
||||
{
|
||||
label: '重置密码',
|
||||
type: 'popconfirm',
|
||||
tip: '确定要重置为123456吗?',
|
||||
props: {
|
||||
onPositiveClick: handlePasswordReset.bind(null, row.id)
|
||||
},
|
||||
ButtonProps: {
|
||||
text: true,
|
||||
type: 'primary'
|
||||
},
|
||||
auth: 'basic_list'
|
||||
},
|
||||
{
|
||||
label: '删除',
|
||||
type: 'popconfirm',
|
||||
auth: 'basic_list',
|
||||
tip: '确定删除这条数据吗?',
|
||||
props: {
|
||||
onPositiveClick: deleteData.bind(null, [row.id])
|
||||
},
|
||||
ButtonProps: {
|
||||
text: true,
|
||||
type: 'primary'
|
||||
}
|
||||
}
|
||||
],
|
||||
align: 'center'
|
||||
})
|
||||
}
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
export default data
|
||||
|
|
@ -1,187 +0,0 @@
|
|||
<template>
|
||||
<Modal
|
||||
:options="getModalOptions"
|
||||
:on-positive-click="handleConfirm"
|
||||
:on-negative-click="handleClose"
|
||||
:on-close="handleClose"
|
||||
>
|
||||
<template #Context>
|
||||
<n-form
|
||||
ref="formRef"
|
||||
:model="form"
|
||||
label-placement="left"
|
||||
:rules="rules"
|
||||
:on-positive-click="handleConfirm"
|
||||
:on-negative-click="handleClose"
|
||||
>
|
||||
<n-form-item label="部门编号:" path="code">
|
||||
<n-input
|
||||
v-model:value="form.code"
|
||||
clearable
|
||||
:maxlength="20"
|
||||
placeholder="请输入部门编号"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item label="部门名称:" path="name">
|
||||
<n-input
|
||||
v-model:value="form.name"
|
||||
clearable
|
||||
:maxlength="20"
|
||||
placeholder="请输入部门名称"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item label="所属部门:" path="pid">
|
||||
<n-select
|
||||
v-model:value="form.pid"
|
||||
:options="getDeptList"
|
||||
placeholder="请选择所属部门"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item label="排序号" path="sort">
|
||||
<n-input-number v-model:value="form.sort" placeholder="请输入排序号" />
|
||||
</n-form-item>
|
||||
<n-form-item
|
||||
label="备注:"
|
||||
>
|
||||
<n-input
|
||||
v-model:value="form.note"
|
||||
type="textarea"
|
||||
:rows="3"
|
||||
:maxlength="200"
|
||||
placeholder="请输入备注"
|
||||
/>
|
||||
</n-form-item>
|
||||
</n-form>
|
||||
</template>
|
||||
</Modal>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defineComponent, computed, reactive, toRefs } from 'vue'
|
||||
import Modal from '@/components/Modal/index.vue'
|
||||
import { addDept, editDept } from '@/api/system/dept/index'
|
||||
export default defineComponent({
|
||||
name: 'UserModal',
|
||||
components: { Modal },
|
||||
props: {
|
||||
visible: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
row: {
|
||||
type: Object,
|
||||
default: () => {}
|
||||
},
|
||||
deptList: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
}
|
||||
},
|
||||
emits: {
|
||||
'update:visible': null,
|
||||
'done': null
|
||||
},
|
||||
setup(props, { emit }) {
|
||||
const data = reactive({
|
||||
form: {
|
||||
avatar: '/images/user/20211011/20211011151447698.jpg',
|
||||
code: '',
|
||||
deptId: null,
|
||||
username: '',
|
||||
realname: '',
|
||||
password: '',
|
||||
roleIds: [],
|
||||
status: 1,
|
||||
note: ''
|
||||
|
||||
},
|
||||
deptOptions: [],
|
||||
rolesOptions: [],
|
||||
rules: {
|
||||
code: [
|
||||
{ required: true, message: '请输入部门编号', trigger: 'blur' }
|
||||
],
|
||||
name: [
|
||||
{ required: true, message: '请输入部门名称', type: 'string', trigger: 'blur' }
|
||||
],
|
||||
sort: [
|
||||
{ required: true, type: 'number', message: '请输入排序号', trigger: 'blur' }
|
||||
]
|
||||
}
|
||||
})
|
||||
// 获取部门选项
|
||||
const getDeptList = computed(() => {
|
||||
const list = props.deptList.map((item) => {
|
||||
const menu = {
|
||||
label: item.name,
|
||||
value: item.id
|
||||
}
|
||||
return menu
|
||||
})
|
||||
return list
|
||||
})
|
||||
|
||||
const getModalOptions = computed(() => {
|
||||
const row = props.row
|
||||
if (props.row.pid === 0) {
|
||||
row.pid = null
|
||||
}
|
||||
console.log('====部门计算属性触发了====', row)
|
||||
return {
|
||||
title: props.row.name ? '修改部门' : '添加部门',
|
||||
show: props.visible,
|
||||
form: Object.assign(data.form, row),
|
||||
negativeText: '取消',
|
||||
positiveText: '确认'
|
||||
}
|
||||
})
|
||||
|
||||
/* 关闭弹窗 */
|
||||
const handleClose = () => {
|
||||
emit('update:visible', false)
|
||||
}
|
||||
|
||||
return {
|
||||
...toRefs(data),
|
||||
getDeptList,
|
||||
getModalOptions,
|
||||
handleClose
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 表单提交
|
||||
handleConfirm() {
|
||||
const type = this.row.name ? 'edit' : 'add'
|
||||
this.$refs.formRef.validate((errors) => {
|
||||
if (!errors) {
|
||||
if (type === 'add') {
|
||||
addDept(this.form).then(res => {
|
||||
if (res.code === 0) {
|
||||
this.handleClose()
|
||||
this.$emit('done')
|
||||
$message.success(res.msg)
|
||||
} else {
|
||||
$message.error(res.msg)
|
||||
}
|
||||
}).catch(e => {
|
||||
console.log(e)
|
||||
})
|
||||
} else if (type === 'edit') {
|
||||
editDept(this.form).then(res => {
|
||||
if (res.code === 0) {
|
||||
this.handleClose()
|
||||
this.$emit('done')
|
||||
$message.success(res.msg)
|
||||
} else {
|
||||
$message.error(res.msg)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
<style scoped lang='scss'>
|
||||
</style>
|
||||
|
|
@ -1,188 +0,0 @@
|
|||
<template>
|
||||
<div>
|
||||
<n-card>
|
||||
<headSearch :info="info" @search="handleSearch" />
|
||||
<data-table
|
||||
ref="tableRef"
|
||||
:columns="columns"
|
||||
:request="loadDataTable"
|
||||
:pagination="false"
|
||||
data-type="tree"
|
||||
size="large"
|
||||
scroll-x="1200"
|
||||
>
|
||||
<template #tableTitle>
|
||||
<n-button type="primary" @click="handleModal"> 新建 </n-button>
|
||||
</template>
|
||||
</data-table>
|
||||
</n-card>
|
||||
</div>
|
||||
<!-- 新增、编辑弹窗 -->
|
||||
<dept-modal
|
||||
v-if="modalShow"
|
||||
v-model:visible="modalShow"
|
||||
:row="rowData"
|
||||
:dept-list="deptList"
|
||||
@done="handleSearch"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import headSearch from '@/components/Search/index.vue'
|
||||
import dataTable from '@/components/DataTable/index.vue'
|
||||
import TableAction from '@/components/DataTable/tools/Action.vue'
|
||||
import {
|
||||
getDeptList,
|
||||
getDeptAll,
|
||||
deleteDept
|
||||
} from '@/api/system/dept/index.js'
|
||||
import { h, unref, toRefs, ref, reactive, onMounted } from 'vue'
|
||||
import DeptModal from './components/DeptModal.vue'
|
||||
import info from './info.js'
|
||||
import table from './table.js'
|
||||
export default {
|
||||
name: 'MenuPage',
|
||||
components: { dataTable, DeptModal, headSearch },
|
||||
setup() {
|
||||
const data = reactive({
|
||||
columns: [
|
||||
...table.columns,
|
||||
{
|
||||
title: '操作',
|
||||
align: 'center',
|
||||
width: 150,
|
||||
fixed: 'right',
|
||||
render(row) {
|
||||
return h(TableAction, {
|
||||
actions: [
|
||||
{
|
||||
label: '添加',
|
||||
type: 'button',
|
||||
props: {
|
||||
type: 'primary',
|
||||
onClick: add.bind(null, row)
|
||||
},
|
||||
auth: 'basic_list'
|
||||
},
|
||||
{
|
||||
label: '修改',
|
||||
type: 'button',
|
||||
props: {
|
||||
type: 'primary',
|
||||
onClick: play.bind(null, row)
|
||||
},
|
||||
auth: 'basic_list'
|
||||
},
|
||||
{
|
||||
label: '删除',
|
||||
type: 'popconfirm',
|
||||
auth: 'basic_list',
|
||||
tip: '确定删除这条数据吗?',
|
||||
props: {
|
||||
negativeText: '取消',
|
||||
positiveText: '确认',
|
||||
onPositiveClick: deleteSingle.bind(null, row.id)
|
||||
}
|
||||
}
|
||||
],
|
||||
align: 'center'
|
||||
})
|
||||
}
|
||||
}
|
||||
],
|
||||
info: ref(info),
|
||||
modalShow: false,
|
||||
rowData: {
|
||||
status: 1,
|
||||
type: 0,
|
||||
hide: 0
|
||||
},
|
||||
deptList: []
|
||||
})
|
||||
|
||||
// 获取全部菜单信息
|
||||
async function getDept() {
|
||||
const list = await getDeptAll()
|
||||
data.deptList = list.data
|
||||
}
|
||||
onMounted(() => {
|
||||
getDept()
|
||||
})
|
||||
/**
|
||||
* @description: 获取部门数据并做树形结构处理
|
||||
* @return {*}
|
||||
*/
|
||||
const params = ref({})
|
||||
|
||||
const tableRef = ref()
|
||||
|
||||
function handleSearch(data) {
|
||||
params.value = {
|
||||
...data
|
||||
}
|
||||
tableRef.value.reFetch({ ...unref(params) })
|
||||
}
|
||||
|
||||
const loadDataTable = async(res) => {
|
||||
const _params = {
|
||||
...unref(params),
|
||||
...res
|
||||
}
|
||||
return await getDeptList(_params)
|
||||
}
|
||||
|
||||
// 新增
|
||||
function handleModal() {
|
||||
data.modalShow = true
|
||||
data.rowData = {}
|
||||
}
|
||||
// 行内新增
|
||||
function add(row) {
|
||||
data.modalShow = true
|
||||
data.rowData = {}
|
||||
data.rowData.pid = row.id
|
||||
}
|
||||
|
||||
// 编辑
|
||||
function play(row) {
|
||||
data.rowData = row
|
||||
data.modalShow = true
|
||||
}
|
||||
|
||||
// 单个删除数据
|
||||
function deleteSingle(id) {
|
||||
deleteData(id)
|
||||
}
|
||||
|
||||
// 删除方法
|
||||
function deleteData(id) {
|
||||
deleteDept(id)
|
||||
.then((res) => {
|
||||
if (res.code === 0) {
|
||||
handleSearch({})
|
||||
$message.success(res.msg)
|
||||
} else {
|
||||
$message.error(res.msg)
|
||||
}
|
||||
})
|
||||
.catch((e) => {
|
||||
console.log(e)
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
...toRefs(data),
|
||||
tableRef,
|
||||
loadDataTable,
|
||||
handleSearch,
|
||||
handleModal,
|
||||
deleteSingle
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style scoped lang='scss'>
|
||||
.n-button + .n-button {
|
||||
margin-left: 10px;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
const table = {
|
||||
columns: [{
|
||||
title: '部门编号',
|
||||
key: 'code',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: '部门名称',
|
||||
key: 'name',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: '排序',
|
||||
key: 'sort',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: '创建时间',
|
||||
key: 'createTime',
|
||||
align: 'center',
|
||||
minWidth: 120
|
||||
},
|
||||
{
|
||||
title: '更新时间',
|
||||
key: 'updateTime',
|
||||
align: 'center',
|
||||
minWidth: 120
|
||||
}]
|
||||
}
|
||||
export default table
|
||||
|
|
@ -1,238 +0,0 @@
|
|||
<template>
|
||||
<Modal
|
||||
:options="getModalOptions"
|
||||
:on-close="handleClose"
|
||||
:on-positive-click="handleConfirm"
|
||||
:on-negative-click="handleClose"
|
||||
>
|
||||
<template #Context>
|
||||
<n-form ref="formRef" :model="form" :rules="rules" require-mark-placement="left" :label-width="80" label-placement="left">
|
||||
<n-grid x-gap="12" :cols="2">
|
||||
<n-gi>
|
||||
<n-form-item label="上级菜单" path="pid">
|
||||
<n-select
|
||||
v-model:value="form.pid"
|
||||
:options="getMenuList"
|
||||
placeholder="请选择上级菜单"
|
||||
/>
|
||||
</n-form-item>
|
||||
</n-gi>
|
||||
<n-gi>
|
||||
<n-form-item label="菜单类型" path="type">
|
||||
<n-radio-group v-model:value="form.type" name="type">
|
||||
<n-radio v-for="item in typeOptions" :key="item.key" :value="item.key">
|
||||
{{ item.label }}
|
||||
</n-radio>
|
||||
</n-radio-group>
|
||||
</n-form-item>
|
||||
</n-gi>
|
||||
<n-gi>
|
||||
<n-form-item label="菜单名称" path="title">
|
||||
<n-input v-model:value="form.title" placeholder="请输入菜单名称" />
|
||||
</n-form-item>
|
||||
</n-gi>
|
||||
<n-gi>
|
||||
<n-form-item label="打开方式" path="target">
|
||||
<n-radio-group v-model:value="form.target" name="target">
|
||||
<n-radio v-for="item in openOptions" :key="item.key" :value="item.key">
|
||||
{{ item.label }}
|
||||
</n-radio>
|
||||
</n-radio-group>
|
||||
</n-form-item>
|
||||
</n-gi>
|
||||
<n-gi>
|
||||
<n-form-item label="菜单图标" path="icon">
|
||||
<n-input v-model:value="form.icon" :disabled="form.type === 1" placeholder="请选择菜单图标" />
|
||||
</n-form-item>
|
||||
</n-gi>
|
||||
<n-gi>
|
||||
<n-form-item label="权限标识" path="permission">
|
||||
<n-input v-model:value="form.permission" :disabled="form.type === 0" placeholder="请输入权限标识" />
|
||||
</n-form-item>
|
||||
</n-gi>
|
||||
<n-gi>
|
||||
<n-form-item label="路由地址" path="path">
|
||||
<n-input v-model:value="form.path" :disabled="form.type === 1" placeholder="请输入路由地址" />
|
||||
</n-form-item>
|
||||
</n-gi>
|
||||
<n-gi>
|
||||
<n-form-item label="排序号" path="sort">
|
||||
<n-input-number v-model:value="form.sort" placeholder="请输入排序号" />
|
||||
</n-form-item>
|
||||
</n-gi>
|
||||
<n-gi>
|
||||
<n-form-item label="组件路径" path="component">
|
||||
<n-input v-model:value="form.component" :disabled="form.type === 1" placeholder="请输入组件路径" />
|
||||
</n-form-item>
|
||||
</n-gi>
|
||||
<n-gi>
|
||||
<n-form-item label="是否可见" path="hide">
|
||||
<n-radio-group v-model:value="form.hide" name="hide">
|
||||
<n-radio v-for="item in visibleOptions" :key="item.key" :value="item.key">
|
||||
{{ item.label }}
|
||||
</n-radio>
|
||||
</n-radio-group>
|
||||
</n-form-item>
|
||||
</n-gi>
|
||||
<n-gi>
|
||||
<n-form-item label="菜单状态" path="status">
|
||||
<n-radio-group v-model:value="form.status" name="status">
|
||||
<n-radio v-for="item in statusOptions" :key="item.key" :value="item.key">
|
||||
{{ item.label }}
|
||||
</n-radio>
|
||||
</n-radio-group>
|
||||
</n-form-item>
|
||||
</n-gi>
|
||||
|
||||
</n-grid>
|
||||
</n-form>
|
||||
</template>
|
||||
</Modal>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defineComponent, computed, reactive, toRefs } from 'vue'
|
||||
import Modal from '@/components/Modal/index.vue'
|
||||
import { addMenu, editMenu } from '@/api/system/menu/index.js'
|
||||
export default defineComponent({
|
||||
name: 'MenuModal',
|
||||
components: { Modal },
|
||||
props: {
|
||||
/* 可见 */
|
||||
visible: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
/* 选中的数据 */
|
||||
data: {
|
||||
type: Object,
|
||||
default: () => {}
|
||||
},
|
||||
menuList: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
}
|
||||
},
|
||||
emits: {
|
||||
'update:visible': null,
|
||||
'done': null
|
||||
},
|
||||
setup(props, { emit }) {
|
||||
const data = reactive({
|
||||
form: {
|
||||
title: '',
|
||||
icon: '',
|
||||
permission: '',
|
||||
path: '',
|
||||
component: '',
|
||||
hide: 0,
|
||||
status: 1
|
||||
},
|
||||
rules: {
|
||||
title: [{
|
||||
required: true,
|
||||
message: '请输入菜单名称',
|
||||
trigger: 'blur'
|
||||
}],
|
||||
sort: [{
|
||||
required: true,
|
||||
type: 'number',
|
||||
message: '请输入排序号',
|
||||
trigger: 'blur'
|
||||
}]
|
||||
},
|
||||
typeOptions: [
|
||||
{ key: 0, label: '菜单' },
|
||||
{ key: 1, label: '按钮' }
|
||||
],
|
||||
openOptions: [
|
||||
{ key: '1', label: '内部' },
|
||||
{ key: '2', label: '外部' }
|
||||
],
|
||||
visibleOptions: [
|
||||
{ key: 0, label: '可见' },
|
||||
{ key: 1, label: '不可见' }
|
||||
],
|
||||
statusOptions: [
|
||||
{ key: 1, label: '在用' },
|
||||
{ key: 2, label: '停用' }
|
||||
]
|
||||
})
|
||||
|
||||
const getMenuList = computed(() => {
|
||||
const list = props.menuList.map((item) => {
|
||||
const menu = {
|
||||
label: item.title,
|
||||
value: item.id
|
||||
}
|
||||
return menu
|
||||
})
|
||||
return list
|
||||
})
|
||||
|
||||
const getModalOptions = computed(() => {
|
||||
const row = props.data
|
||||
if (props.data.pid === 0) {
|
||||
row.pid = null
|
||||
}
|
||||
console.log('菜单页面计算属性触发:', row)
|
||||
return {
|
||||
title: props.data.title ? '修改菜单' : '添加菜单',
|
||||
show: props.visible,
|
||||
form: Object.assign(data.form, row),
|
||||
negativeText: '取消',
|
||||
positiveText: '确认'
|
||||
}
|
||||
})
|
||||
|
||||
/* 关闭弹窗 */
|
||||
const handleClose = () => {
|
||||
emit('update:visible', false)
|
||||
}
|
||||
|
||||
return {
|
||||
...toRefs(data),
|
||||
getMenuList,
|
||||
getModalOptions,
|
||||
handleClose
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 表单提交
|
||||
handleConfirm() {
|
||||
const type = this.data.title ? 'edit' : 'add'
|
||||
this.$refs.formRef.validate((errors) => {
|
||||
if (!errors) {
|
||||
if (type === 'add') {
|
||||
addMenu(this.form).then(res => {
|
||||
if (res.code === 0) {
|
||||
this.handleClose()
|
||||
this.$emit('done')
|
||||
$message.success(res.msg)
|
||||
} else {
|
||||
$message.error(res.msg)
|
||||
}
|
||||
}).catch(e => {
|
||||
console.log(e)
|
||||
})
|
||||
} else if (type === 'edit') {
|
||||
editMenu(this.form).then(res => {
|
||||
if (res.code === 0) {
|
||||
this.handleClose()
|
||||
this.$emit('done')
|
||||
$message.success(res.msg)
|
||||
} else {
|
||||
$message.error(res.msg)
|
||||
}
|
||||
})
|
||||
}
|
||||
} else {
|
||||
$message.error('请完善必填信息')
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
<style scoped lang='scss'>
|
||||
</style>
|
||||
|
|
@ -1,177 +0,0 @@
|
|||
<template>
|
||||
<div>
|
||||
<n-card>
|
||||
<headSearch :info="info" />
|
||||
<!-- <data-table
|
||||
ref="tableRef"
|
||||
:columns="columns"
|
||||
:pagination="false"
|
||||
data-type="tree"
|
||||
:request="loadDataTable"
|
||||
>
|
||||
<template #tableTitle>
|
||||
<n-button type="primary" @click="handleModal"> 添加菜单 </n-button>
|
||||
</template>
|
||||
</data-table> -->
|
||||
</n-card>
|
||||
</div>
|
||||
|
||||
<MenuModal
|
||||
v-if="modalShow"
|
||||
v-model:visible="modalShow"
|
||||
:data="rowData"
|
||||
:menu-list="menuList"
|
||||
@done="handleSearch"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import headSearch from '@/components/Search/index.vue'
|
||||
import dataTable from '@/components/DataTable/index.vue'
|
||||
import MenuModal from './components/MenuModal.vue'
|
||||
import Action from '@/components/DataTable/tools/Action.vue'
|
||||
import { getMenu, getMenuList, deleteMenu } from '@/api/system/menu/index.js'
|
||||
import { h, ref, unref, reactive, toRefs, onMounted } from 'vue'
|
||||
import info from './info.js'
|
||||
import table from './table.js'
|
||||
export default {
|
||||
name: 'MenuPage',
|
||||
components: { dataTable, MenuModal, headSearch },
|
||||
setup() {
|
||||
const data = reactive({
|
||||
columns: [
|
||||
...table.columns,
|
||||
{
|
||||
title: '操作',
|
||||
align: 'center',
|
||||
width: 150,
|
||||
fixed: 'right',
|
||||
render(row) {
|
||||
return h(Action, {
|
||||
actions: [
|
||||
{
|
||||
label: '添加',
|
||||
type: 'button',
|
||||
props: {
|
||||
type: 'primary',
|
||||
onClick: add.bind(null, row)
|
||||
},
|
||||
auth: 'basic_list'
|
||||
},
|
||||
{
|
||||
label: '修改',
|
||||
type: 'button',
|
||||
props: {
|
||||
type: 'primary',
|
||||
onClick: play.bind(null, row)
|
||||
},
|
||||
auth: 'basic_list'
|
||||
},
|
||||
{
|
||||
label: '删除',
|
||||
type: 'popconfirm',
|
||||
auth: 'basic_list',
|
||||
tip: '确定删除这条数据吗?',
|
||||
props: {
|
||||
negativeText: '取消',
|
||||
positiveText: '确认',
|
||||
onPositiveClick: deleteSingle.bind(null, row.id)
|
||||
}
|
||||
}
|
||||
],
|
||||
align: 'center'
|
||||
})
|
||||
}
|
||||
}
|
||||
],
|
||||
info: ref(info),
|
||||
modalShow: false,
|
||||
menuList: [],
|
||||
rowData: {
|
||||
status: 1,
|
||||
type: 0,
|
||||
hide: 0
|
||||
}
|
||||
})
|
||||
|
||||
// 获取全部菜单信息
|
||||
async function getMenuAll() {
|
||||
const list = await getMenu()
|
||||
data.menuList = list.data
|
||||
}
|
||||
onMounted(() => {
|
||||
getMenuAll()
|
||||
})
|
||||
|
||||
/**
|
||||
* @description: 获取菜单数据
|
||||
* @return {*}
|
||||
*/
|
||||
const params = ref({})
|
||||
const tableRef = ref()
|
||||
|
||||
function handleSearch(data) {
|
||||
params.value = {
|
||||
...data
|
||||
}
|
||||
tableRef.value.reFetch({ ...unref(params) })
|
||||
}
|
||||
|
||||
const loadDataTable = async(res) => {
|
||||
const _params = {
|
||||
...unref(params),
|
||||
...res
|
||||
}
|
||||
return await getMenuList(_params)
|
||||
}
|
||||
|
||||
// 打开新增弹框
|
||||
function handleModal() {
|
||||
data.modalShow = true
|
||||
data.rowData = {}
|
||||
}
|
||||
// 行内新增
|
||||
function add(row) {
|
||||
data.modalShow = true
|
||||
data.rowData = {}
|
||||
data.rowData.pid = row.id
|
||||
}
|
||||
// 编辑
|
||||
function play(row) {
|
||||
data.rowData = row
|
||||
data.modalShow = true
|
||||
}
|
||||
// 单个删除数据
|
||||
function deleteSingle(id) {
|
||||
deleteData(id)
|
||||
}
|
||||
|
||||
// 删除方法
|
||||
function deleteData(id) {
|
||||
deleteMenu(id)
|
||||
.then((res) => {
|
||||
if (res.code === 0) {
|
||||
handleSearch({})
|
||||
$message.success(res.msg)
|
||||
} else {
|
||||
$message.error(res.msg)
|
||||
}
|
||||
})
|
||||
.catch((e) => {
|
||||
console.log(e)
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
...toRefs(data),
|
||||
tableRef,
|
||||
loadDataTable,
|
||||
handleSearch,
|
||||
handleModal,
|
||||
deleteSingle
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style scoped lang='scss'>
|
||||
</style>
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
const data = [
|
||||
{
|
||||
label: '菜单名称',
|
||||
type: 'area',
|
||||
key: 'name',
|
||||
refIndex: 0,
|
||||
props: {
|
||||
placeholder: '请输入菜单名称',
|
||||
options: [{ label: 1, value: 1, children: [{ label: '1-1', value: '1-1' }] }]
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
export default data
|
||||
|
||||
|
|
@ -1,101 +0,0 @@
|
|||
import { h } from 'vue'
|
||||
import TableTags from '@/components/DataTable/tools/Tags.vue'
|
||||
const table = {
|
||||
columns: [
|
||||
{
|
||||
title: '菜单标题',
|
||||
key: 'title',
|
||||
align: 'center',
|
||||
width: 200
|
||||
},
|
||||
{
|
||||
title: '菜单类型',
|
||||
key: 'type',
|
||||
align: 'center',
|
||||
width: 100,
|
||||
render(row) {
|
||||
return h(TableTags, {
|
||||
data: row.type,
|
||||
filters: [
|
||||
{
|
||||
key: 0,
|
||||
label: '菜单'
|
||||
},
|
||||
{
|
||||
key: 1,
|
||||
label: '节点'
|
||||
}
|
||||
]
|
||||
})
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '路由地址',
|
||||
key: 'path',
|
||||
align: 'center',
|
||||
width: 200
|
||||
},
|
||||
{
|
||||
title: '组件路径',
|
||||
key: 'component',
|
||||
align: 'center',
|
||||
width: 200
|
||||
},
|
||||
{
|
||||
title: '状态',
|
||||
key: 'status',
|
||||
align: 'center',
|
||||
width: 100,
|
||||
render(row) {
|
||||
return h(TableTags, {
|
||||
data: row.status,
|
||||
filters: [
|
||||
{
|
||||
key: 1,
|
||||
label: '在用'
|
||||
},
|
||||
{
|
||||
key: 2,
|
||||
label: '停用'
|
||||
}
|
||||
]
|
||||
})
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '排序',
|
||||
key: 'sort',
|
||||
align: 'center',
|
||||
width: 100
|
||||
},
|
||||
{
|
||||
title: '是否可见',
|
||||
key: 'hide',
|
||||
align: 'center',
|
||||
width: 100,
|
||||
render(row) {
|
||||
return h(TableTags, {
|
||||
data: row.hide,
|
||||
filters: [
|
||||
{
|
||||
key: 1,
|
||||
label: '可见'
|
||||
},
|
||||
{
|
||||
key: 2,
|
||||
label: '不可见'
|
||||
}
|
||||
]
|
||||
})
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '创建时间',
|
||||
key: 'createTime',
|
||||
align: 'center',
|
||||
width: 160
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
export default table
|
||||
|
|
@ -1,166 +0,0 @@
|
|||
<template>
|
||||
<Modal
|
||||
:options="getModalOptions"
|
||||
:on-positive-click="handleConfirm"
|
||||
:on-negative-click="handleClose"
|
||||
:on-close="handleClose"
|
||||
>
|
||||
<template #Context>
|
||||
<n-form
|
||||
ref="formRef"
|
||||
:model="form"
|
||||
label-placement="left"
|
||||
:rules="rules"
|
||||
:on-positive-click="handleConfirm"
|
||||
:on-negative-click="handleClose"
|
||||
>
|
||||
<n-form-item label="角色编号:" path="code">
|
||||
<n-input
|
||||
v-model:value="form.code"
|
||||
clearable
|
||||
:maxlength="20"
|
||||
placeholder="请输入角色编号"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item label="角色名称:" path="name">
|
||||
<n-input
|
||||
v-model:value="form.name"
|
||||
clearable
|
||||
:maxlength="20"
|
||||
placeholder="请输入角色名称"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item label="状态" path="status">
|
||||
<n-radio-group
|
||||
v-model:value="form.status"
|
||||
>
|
||||
<n-radio :value="1">正常</n-radio>
|
||||
<n-radio :value="2">禁用</n-radio>
|
||||
</n-radio-group>
|
||||
</n-form-item>
|
||||
<n-form-item
|
||||
label="备注:"
|
||||
>
|
||||
<n-input
|
||||
v-model:value="form.note"
|
||||
type="textarea"
|
||||
:rows="3"
|
||||
:maxlength="200"
|
||||
placeholder="请输入备注"
|
||||
/>
|
||||
</n-form-item>
|
||||
</n-form>
|
||||
</template>
|
||||
</Modal>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defineComponent, computed, reactive, toRefs } from 'vue'
|
||||
import Modal from '@/components/Modal/index.vue'
|
||||
import { addRole, editRole } from '@/api/system/role/index'
|
||||
export default defineComponent({
|
||||
name: 'RoleModal',
|
||||
components: { Modal },
|
||||
props: {
|
||||
visible: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
row: {
|
||||
type: Object,
|
||||
default: () => {}
|
||||
}
|
||||
},
|
||||
emits: {
|
||||
'update:visible': null,
|
||||
'done': null
|
||||
},
|
||||
setup(props, { emit }) {
|
||||
const data = reactive({
|
||||
form: {
|
||||
code: '',
|
||||
name: '',
|
||||
status: 1,
|
||||
note: ''
|
||||
},
|
||||
rules: {
|
||||
code: [
|
||||
{ required: true, message: '请输入角色编号', trigger: 'blur' }
|
||||
],
|
||||
name: [
|
||||
{ required: true, message: '请输入角色名称', type: 'string', trigger: 'blur' }
|
||||
],
|
||||
status: [
|
||||
{ required: true, message: '请选择状态', type: 'number', trigger: 'blur' }
|
||||
]
|
||||
}
|
||||
})
|
||||
const getModalOptions = computed(() => {
|
||||
return {
|
||||
title: Object.keys(props.row).length === 0 ? '添加角色' : '编辑角色',
|
||||
show: props.visible,
|
||||
form: Object.assign(data.form, props.row),
|
||||
negativeText: '取消',
|
||||
positiveText: '确认'
|
||||
}
|
||||
})
|
||||
|
||||
/* 关闭弹窗 */
|
||||
const handleClose = () => {
|
||||
emit('update:visible', false)
|
||||
}
|
||||
|
||||
return {
|
||||
getModalOptions,
|
||||
handleClose,
|
||||
...toRefs(data),
|
||||
rules: reactive({
|
||||
code: [
|
||||
{ required: true, message: '请输入角色编号', trigger: 'blur' }
|
||||
],
|
||||
name: [
|
||||
{ required: true, message: '请输入角色名称', type: 'string', trigger: 'blur' }
|
||||
],
|
||||
status: [
|
||||
{ required: true, message: '请选择状态', type: 'number', trigger: 'blur' }
|
||||
]
|
||||
})
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 表单提交
|
||||
handleConfirm() {
|
||||
const type = Object.keys(this.row).length === 0 ? 'add' : 'edit'
|
||||
this.$refs.formRef.validate((errors) => {
|
||||
if (!errors) {
|
||||
if (type === 'add') {
|
||||
addRole(this.form).then(res => {
|
||||
if (res.code === 0) {
|
||||
this.handleClose()
|
||||
this.$emit('done')
|
||||
$message.success(res.msg)
|
||||
} else {
|
||||
$message.error(res.msg)
|
||||
}
|
||||
}).catch(e => {
|
||||
console.log(e)
|
||||
})
|
||||
} else if (type === 'edit') {
|
||||
editRole(this.form).then(res => {
|
||||
if (res.code === 0) {
|
||||
this.handleClose()
|
||||
this.$emit('done')
|
||||
$message.success(res.msg)
|
||||
} else {
|
||||
$message.error(res.msg)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
<style scoped lang='scss'>
|
||||
</style>
|
||||
|
|
@ -1,239 +0,0 @@
|
|||
<template>
|
||||
<div>
|
||||
<n-card>
|
||||
<headSearch :info="info" @search="handleSearch" />
|
||||
<data-table
|
||||
ref="tableRef"
|
||||
:columns="columns"
|
||||
:row-key="(row) => row.id"
|
||||
:request="loadDataTable"
|
||||
size="large"
|
||||
scroll-x="1200"
|
||||
@update:checked-row-keys="handleCheck"
|
||||
>
|
||||
<template #tableTitle>
|
||||
<n-button type="primary" @click="handleModal"> 新建 </n-button>
|
||||
<n-popconfirm
|
||||
negative-text="取消"
|
||||
positive-text="确认"
|
||||
@positive-click="deleteComplex"
|
||||
>
|
||||
<template #trigger>
|
||||
<n-button type="primary">删除</n-button>
|
||||
</template>
|
||||
确定删除选中的数据吗?
|
||||
</n-popconfirm>
|
||||
</template>
|
||||
</data-table>
|
||||
</n-card>
|
||||
</div>
|
||||
<!-- 新增、编辑弹窗 -->
|
||||
<role-modal
|
||||
v-if="modalShow"
|
||||
v-model:visible="modalShow"
|
||||
:row="rowData"
|
||||
@done="handleSearch"
|
||||
/>
|
||||
<!-- 分配权限 -->
|
||||
<config-modal
|
||||
v-if="configModalShow"
|
||||
v-model:visible="configModalShow"
|
||||
:row="rowData"
|
||||
@done="handleSearch"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import headSearch from '@/components/Search/index.vue'
|
||||
import dataTable from '@/components/DataTable/index.vue'
|
||||
import TableAction from '@/components/DataTable/tools/Action.vue'
|
||||
import TableSwitch from '@/components/DataTable/tools/Switch.vue'
|
||||
import {
|
||||
getRoleList,
|
||||
deleteRole,
|
||||
setRoleStatus
|
||||
} from '@/api/system/role/index'
|
||||
import { h, ref, unref, toRefs, reactive } from 'vue'
|
||||
import table from './table.js'
|
||||
import info from './info.js'
|
||||
import RoleModal from './components/RoleModal.vue'
|
||||
import ConfigModal from './components/ConfigModal.vue'
|
||||
|
||||
export default {
|
||||
name: 'MenuPage',
|
||||
components: { headSearch, dataTable, RoleModal, ConfigModal },
|
||||
setup() {
|
||||
const data = reactive({
|
||||
columns: [
|
||||
...table.columns,
|
||||
{
|
||||
title: '状态',
|
||||
key: 'status',
|
||||
align: 'center',
|
||||
width: 100,
|
||||
render(row) {
|
||||
return h(TableSwitch, {
|
||||
data: { id: row.id, status: row.status },
|
||||
rowKey: 'status',
|
||||
checkedValue: 1,
|
||||
uncheckedValue: 2,
|
||||
onChange: setStatus.bind(row)
|
||||
})
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
align: 'center',
|
||||
width: 150,
|
||||
fixed: 'right',
|
||||
render(row) {
|
||||
return h(TableAction, {
|
||||
actions: [
|
||||
{
|
||||
label: '修改',
|
||||
type: 'button',
|
||||
props: {
|
||||
type: 'primary',
|
||||
onClick: play.bind(null, row)
|
||||
},
|
||||
auth: 'basic_list'
|
||||
},
|
||||
{
|
||||
label: '分配权限',
|
||||
type: 'button',
|
||||
props: {
|
||||
type: 'primary',
|
||||
ghost: true,
|
||||
onClick: configure.bind(null, row)
|
||||
},
|
||||
auth: 'basic_list'
|
||||
},
|
||||
{
|
||||
label: '删除',
|
||||
type: 'popconfirm',
|
||||
auth: 'basic_list',
|
||||
tip: '确定删除这条数据吗?',
|
||||
props: {
|
||||
negativeText: '取消',
|
||||
positiveText: '确认',
|
||||
onPositiveClick: deleteSingle.bind(null, row.id)
|
||||
}
|
||||
}
|
||||
],
|
||||
align: 'center'
|
||||
})
|
||||
}
|
||||
}
|
||||
],
|
||||
info: ref(info),
|
||||
modalShow: false,
|
||||
configModalShow: false,
|
||||
rowData: {}
|
||||
})
|
||||
// 编辑
|
||||
function play(row) {
|
||||
data.rowData = row
|
||||
data.modalShow = true
|
||||
}
|
||||
|
||||
// 配置权限
|
||||
function configure(row) {
|
||||
data.rowData = row
|
||||
data.configModalShow = true
|
||||
}
|
||||
|
||||
const params = ref({})
|
||||
const tableRef = ref()
|
||||
function handleSearch(data) {
|
||||
params.value = {
|
||||
...data
|
||||
}
|
||||
tableRef.value.reFetch({ ...unref(params) })
|
||||
}
|
||||
|
||||
const loadDataTable = async(res) => {
|
||||
const _params = {
|
||||
...unref(params),
|
||||
...res
|
||||
}
|
||||
return await getRoleList(_params)
|
||||
}
|
||||
|
||||
// 新增用户
|
||||
function handleModal() {
|
||||
data.rowData = {}
|
||||
data.modalShow = true
|
||||
}
|
||||
|
||||
// 选择表格数据
|
||||
const selectedIds = ref([])
|
||||
function handleCheck(rowKeys) {
|
||||
selectedIds.value = rowKeys
|
||||
}
|
||||
// 批量删除
|
||||
function deleteComplex() {
|
||||
if (selectedIds.value.length) {
|
||||
deleteData(selectedIds.value)
|
||||
} else {
|
||||
$message.warning('请至少选中一条数据')
|
||||
}
|
||||
}
|
||||
// 单个删除数据
|
||||
function deleteSingle(id) {
|
||||
deleteData([id])
|
||||
}
|
||||
|
||||
// 删除接口
|
||||
function deleteData(data) {
|
||||
deleteRole(data)
|
||||
.then((res) => {
|
||||
if (res.code === 0) {
|
||||
handleSearch()
|
||||
$message.success(res.msg)
|
||||
} else {
|
||||
$message.error(res.msg)
|
||||
}
|
||||
})
|
||||
.catch((e) => {
|
||||
console.log(e)
|
||||
})
|
||||
}
|
||||
|
||||
// 设置状态
|
||||
function setStatus(row) {
|
||||
console.log(row)
|
||||
setRoleStatus({ id: row.data.id, status: row.value })
|
||||
.then((res) => {
|
||||
if (res.code === 0) {
|
||||
handleSearch()
|
||||
$message.success(res.msg)
|
||||
} else {
|
||||
$message.error(res.msg)
|
||||
}
|
||||
})
|
||||
.catch((e) => {
|
||||
console.log(e)
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
...toRefs(data),
|
||||
tableRef,
|
||||
loadDataTable,
|
||||
handleSearch,
|
||||
handleModal,
|
||||
handleCheck,
|
||||
selectedIds,
|
||||
deleteSingle,
|
||||
deleteComplex,
|
||||
deleteData,
|
||||
setStatus
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style scoped lang='scss'>
|
||||
.n-button + .n-button {
|
||||
margin-left: 10px;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
|
||||
const data = {
|
||||
columns: [
|
||||
{ type: 'selection' },
|
||||
{
|
||||
title: '角色编号',
|
||||
key: 'code',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: '角色名称',
|
||||
key: 'name',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: '创建时间',
|
||||
key: 'createTime',
|
||||
align: 'center',
|
||||
Minwidth: 160
|
||||
},
|
||||
{
|
||||
title: '更新时间',
|
||||
key: 'updateTime',
|
||||
align: 'center',
|
||||
Minwidth: 160
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
export default data
|
||||
|
|
@ -1,251 +0,0 @@
|
|||
<template>
|
||||
<Modal
|
||||
:options="getModalOptions"
|
||||
:on-positive-click="handleConfirm"
|
||||
:on-negative-click="handleClose"
|
||||
:on-close="handleClose"
|
||||
>
|
||||
<template #Context>
|
||||
<n-form
|
||||
ref="formRef"
|
||||
:model="form"
|
||||
label-placement="left"
|
||||
:rules="rules"
|
||||
:on-positive-click="handleConfirm"
|
||||
:on-negative-click="handleClose"
|
||||
>
|
||||
<n-form-item
|
||||
label="头像:"
|
||||
path="avatar"
|
||||
>
|
||||
<uploadImage
|
||||
:options="{
|
||||
max:1,
|
||||
action: '/upload/uploadImage/demo',
|
||||
}"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item label="用户编号:" path="code">
|
||||
<n-input
|
||||
v-model:value="form.code"
|
||||
clearable
|
||||
:maxlength="20"
|
||||
placeholder="请输入用户编号"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item label="用户账号:" path="username">
|
||||
<n-input
|
||||
v-model:value="form.username"
|
||||
clearable
|
||||
:maxlength="20"
|
||||
placeholder="请输入用户账号"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item
|
||||
label="登录密码:"
|
||||
path="password"
|
||||
>
|
||||
<n-input
|
||||
v-model:value="form.password"
|
||||
type="password"
|
||||
:maxlength="20"
|
||||
placeholder="请输入登录密码"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item label="用户姓名:" path="realname">
|
||||
<n-input
|
||||
v-model:value="form.realname"
|
||||
clearable
|
||||
:maxlength="20"
|
||||
placeholder="请输入用户姓名"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item label="所属部门:" path="deptId">
|
||||
<n-select
|
||||
v-model:value="form.deptId"
|
||||
:options="deptOptions"
|
||||
placeholder="请选择所属部门"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item label="角色:" path="roleIds">
|
||||
<n-select
|
||||
v-model:value="form.roleIds"
|
||||
clearable
|
||||
:multiple="true"
|
||||
:options="rolesOptions"
|
||||
placeholder="请选择角色"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item label="状态" path="status">
|
||||
<n-radio-group
|
||||
v-model:value="form.status"
|
||||
>
|
||||
<n-radio :value="1">正常</n-radio>
|
||||
<n-radio :value="2">禁用</n-radio>
|
||||
</n-radio-group>
|
||||
</n-form-item>
|
||||
<n-form-item
|
||||
label="备注:"
|
||||
>
|
||||
<n-input
|
||||
v-model:value="form.note"
|
||||
type="textarea"
|
||||
:rows="3"
|
||||
:maxlength="200"
|
||||
placeholder="请输入备注"
|
||||
/>
|
||||
</n-form-item>
|
||||
</n-form>
|
||||
</template>
|
||||
</Modal>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defineComponent, computed, onMounted, reactive, toRefs } from 'vue'
|
||||
import Modal from '@/components/Modal/index.vue'
|
||||
import uploadImage from '@/components/ImgUpload/index.vue'
|
||||
import { getDeptAll } from '@/api/system/dept/index'
|
||||
import { getRoleAll } from '@/api/system/role/index'
|
||||
import { addUser, editUser } from '@/api/system/user/index'
|
||||
import { dataToSelect } from '@/utils/handleData.js'
|
||||
export default defineComponent({
|
||||
name: 'UserModal',
|
||||
components: { Modal, uploadImage },
|
||||
props: {
|
||||
visible: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
row: {
|
||||
type: Object,
|
||||
default: () => {}
|
||||
}
|
||||
},
|
||||
emits: {
|
||||
'update:visible': null,
|
||||
'done': null
|
||||
},
|
||||
setup(props, { emit }) {
|
||||
const data = reactive({
|
||||
form: {
|
||||
avatar: '/images/user/20211011/20211011151447698.jpg',
|
||||
code: '',
|
||||
deptId: null,
|
||||
username: '',
|
||||
realname: '',
|
||||
password: '',
|
||||
roleIds: [],
|
||||
status: 1,
|
||||
note: ''
|
||||
|
||||
},
|
||||
deptOptions: [],
|
||||
rolesOptions: [],
|
||||
rules: {
|
||||
avatar: [
|
||||
{ required: true, message: '请选择头像', type: 'string', trigger: 'blur' }
|
||||
],
|
||||
code: [
|
||||
{ required: true, message: '请输入编号', trigger: 'blur' }
|
||||
],
|
||||
realname: [
|
||||
{ required: true, message: '请输入用户姓名', type: 'string', trigger: 'blur' }
|
||||
],
|
||||
deptId: [
|
||||
{ required: true, message: '请选择部门', type: 'number', trigger: 'blur' }
|
||||
],
|
||||
status: [
|
||||
{ required: true, message: '请选择状态', type: 'number', trigger: 'blur' }
|
||||
],
|
||||
roleIds: [
|
||||
{ required: true, message: '请选择角色', type: 'array', trigger: 'blur' }
|
||||
],
|
||||
username: [
|
||||
{ required: true, message: '请输入用户账号', type: 'string', trigger: 'blur' }
|
||||
]
|
||||
}
|
||||
})
|
||||
const getModalOptions = computed(() => {
|
||||
return {
|
||||
title: Object.keys(props.row).length === 0 ? '添加用户' : '编辑用户',
|
||||
show: props.visible,
|
||||
form: Object.assign(data.form, props.row),
|
||||
negativeText: '取消',
|
||||
positiveText: '确认'
|
||||
}
|
||||
})
|
||||
|
||||
/* 关闭弹窗 */
|
||||
const handleClose = () => {
|
||||
emit('update:visible', false)
|
||||
}
|
||||
|
||||
// 获取部门列表
|
||||
async function getDeptOptions() {
|
||||
const res = await getDeptAll()
|
||||
data.deptOptions = dataToSelect(res.data, { label: 'name', value: 'id' })
|
||||
}
|
||||
|
||||
// 获取角色列表
|
||||
async function getRoleOptions() {
|
||||
const res = await getRoleAll()
|
||||
data.rolesOptions = dataToSelect(res.data, { label: 'name', value: 'id' })
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
getDeptOptions()
|
||||
getRoleOptions()
|
||||
})
|
||||
|
||||
// 上传文件
|
||||
const handleUpload = ({ file }) => {
|
||||
console.log(file)
|
||||
// data.form.avatar = file.url
|
||||
}
|
||||
|
||||
return {
|
||||
...toRefs(data),
|
||||
getModalOptions,
|
||||
handleClose,
|
||||
handleUpload
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 表单提交
|
||||
handleConfirm() {
|
||||
const type = Object.keys(this.row).length === 0 ? 'add' : 'edit'
|
||||
this.$refs.formRef.validate((errors) => {
|
||||
if (!errors) {
|
||||
if (type === 'add') {
|
||||
addUser(this.form).then(res => {
|
||||
if (res.code === 0) {
|
||||
this.handleClose()
|
||||
this.$emit('done')
|
||||
$message.success(res.msg)
|
||||
} else {
|
||||
$message.error(res.msg)
|
||||
}
|
||||
}).catch(e => {
|
||||
console.log(e)
|
||||
})
|
||||
} else if (type === 'edit') {
|
||||
editUser(this.form).then(res => {
|
||||
if (res.code === 0) {
|
||||
this.handleClose()
|
||||
this.$emit('done')
|
||||
$message.success(res.msg)
|
||||
} else {
|
||||
$message.error(res.msg)
|
||||
}
|
||||
})
|
||||
}
|
||||
} else {
|
||||
$message.error('请完善必填信息')
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
<style scoped lang='scss'>
|
||||
</style>
|
||||
|
|
@ -1,233 +0,0 @@
|
|||
<template>
|
||||
<div>
|
||||
<n-card>
|
||||
<headSearch :info="info" @search="handleSearch" />
|
||||
<data-table
|
||||
ref="tableRef"
|
||||
:columns="columns"
|
||||
:row-key="(row) => row.id"
|
||||
:request="loadDataTable"
|
||||
size="large"
|
||||
@update:checked-row-keys="handleCheck"
|
||||
>
|
||||
<template #tableTitle>
|
||||
<n-button type="primary" @click="handleModal"> 新建 </n-button>
|
||||
<n-popconfirm
|
||||
negative-text="取消"
|
||||
positive-text="确认"
|
||||
@positive-click="deleteComplex"
|
||||
>
|
||||
<template #trigger>
|
||||
<n-button type="primary"> 删除 </n-button>
|
||||
</template>
|
||||
确认要删除选中数据吗?
|
||||
</n-popconfirm>
|
||||
</template>
|
||||
</data-table>
|
||||
</n-card>
|
||||
</div>
|
||||
<!-- 新增、编辑弹窗 -->
|
||||
<user-modal
|
||||
v-if="modalShow"
|
||||
v-model:visible="modalShow"
|
||||
:row="rowData"
|
||||
@done="handleSearch"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import headSearch from '@/components/Search/index.vue'
|
||||
import dataTable from '@/components/DataTable/index.vue'
|
||||
import TableSwitch from '@/components/DataTable/tools/Switch.vue'
|
||||
import TableAction from '@/components/DataTable/tools/Action.vue'
|
||||
import { getUserList, resetPassword, deleteUser, setUserStatus } from '@/api/system/user/index.js'
|
||||
import { h, unref, ref, toRefs, reactive } from 'vue'
|
||||
import UserModal from './components/UserModal.vue'
|
||||
import info from './info.js'
|
||||
import table from './table.js'
|
||||
export default {
|
||||
name: 'MenuPage',
|
||||
components: { dataTable, UserModal, headSearch },
|
||||
setup() {
|
||||
const data = reactive({
|
||||
columns: [
|
||||
...table.columns,
|
||||
{
|
||||
title: '状态',
|
||||
key: 'status',
|
||||
align: 'center',
|
||||
width: 100,
|
||||
render(row) {
|
||||
return h(TableSwitch, {
|
||||
data: { id: row.id, status: row.status },
|
||||
rowKey: 'status',
|
||||
checkedValue: 1,
|
||||
uncheckedValue: 2,
|
||||
onChange: setStatus.bind(row)
|
||||
})
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
align: 'center',
|
||||
width: 150,
|
||||
fixed: 'right',
|
||||
render(row) {
|
||||
return h(TableAction, {
|
||||
actions: [
|
||||
{
|
||||
label: '修改',
|
||||
type: 'button',
|
||||
props: {
|
||||
type: 'primary',
|
||||
onClick: play.bind(null, row)
|
||||
},
|
||||
auth: 'basic_list'
|
||||
},
|
||||
{
|
||||
label: '重置密码',
|
||||
type: 'popconfirm',
|
||||
auth: 'basic_list',
|
||||
tip: '确定要重置为123456吗?',
|
||||
props: {
|
||||
negativeText: '取消',
|
||||
positiveText: '确认',
|
||||
onPositiveClick: resetPsw.bind(null, row.id)
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '删除',
|
||||
type: 'popconfirm',
|
||||
auth: 'basic_list',
|
||||
tip: '确定删除这条数据吗?',
|
||||
props: {
|
||||
negativeText: '取消',
|
||||
positiveText: '确认',
|
||||
onPositiveClick: deleteSingle.bind(null, row.id)
|
||||
}
|
||||
}
|
||||
],
|
||||
align: 'center'
|
||||
})
|
||||
}
|
||||
}
|
||||
],
|
||||
info: ref(info),
|
||||
modalShow: false,
|
||||
rowData: {}
|
||||
})
|
||||
// 打开编辑弹窗
|
||||
function play(row) {
|
||||
data.rowData = row
|
||||
data.modalShow = true
|
||||
}
|
||||
|
||||
const params = ref({})
|
||||
|
||||
const tableRef = ref()
|
||||
|
||||
function handleSearch(data) {
|
||||
params.value = {
|
||||
...data
|
||||
}
|
||||
tableRef.value.reFetch({ ...unref(params) })
|
||||
}
|
||||
|
||||
const loadDataTable = async(res) => {
|
||||
const _params = {
|
||||
...unref(params),
|
||||
...res
|
||||
}
|
||||
return await getUserList(_params)
|
||||
}
|
||||
|
||||
// 新增
|
||||
function handleModal() {
|
||||
data.rowData = {}
|
||||
data.modalShow = true
|
||||
}
|
||||
|
||||
// 选择表格数据
|
||||
const selectedIds = ref([])
|
||||
function handleCheck(rowKeys) {
|
||||
selectedIds.value = rowKeys
|
||||
}
|
||||
// 批量删除
|
||||
function deleteComplex() {
|
||||
if (selectedIds.value.length) {
|
||||
deleteData(selectedIds.value)
|
||||
} else {
|
||||
$message.warning('请至少选中一条数据')
|
||||
}
|
||||
}
|
||||
// 单个删除数据
|
||||
function deleteSingle(id) {
|
||||
deleteData([id])
|
||||
}
|
||||
|
||||
// 删除用户接口
|
||||
function deleteData(data) {
|
||||
deleteUser(data).then((res) => {
|
||||
if (res.code === 0) {
|
||||
handleSearch()
|
||||
$message.success(res.msg)
|
||||
} else {
|
||||
$message.error(res.msg)
|
||||
}
|
||||
}).catch(e => {
|
||||
console.log(e)
|
||||
})
|
||||
}
|
||||
|
||||
// 重置密码
|
||||
function resetPsw(id) {
|
||||
resetPassword({ id }).then(res => {
|
||||
if (res.code === 0) {
|
||||
handleSearch()
|
||||
$message.success(res.msg)
|
||||
} else {
|
||||
$message.error(res.msg)
|
||||
}
|
||||
}).catch(e => {
|
||||
console.log(e)
|
||||
})
|
||||
}
|
||||
|
||||
// 设置状态
|
||||
function setStatus(row) {
|
||||
setUserStatus({ id: row.data.id, status: row.value }).then(res => {
|
||||
if (res.code === 0) {
|
||||
handleSearch()
|
||||
$message.success(res.msg)
|
||||
} else {
|
||||
$message.error(res.msg)
|
||||
}
|
||||
}).catch(e => {
|
||||
console.log(e)
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
loadDataTable,
|
||||
handleModal,
|
||||
...toRefs(data),
|
||||
tableRef,
|
||||
handleSearch,
|
||||
selectedIds,
|
||||
deleteComplex,
|
||||
handleCheck,
|
||||
deleteData,
|
||||
resetPsw,
|
||||
setStatus
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style scoped lang='scss'>
|
||||
.n-button + .n-button {
|
||||
margin-left: 10px;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
import { getRoleAll } from '@/api/system/role/index'
|
||||
import { dataToSelect } from '@/utils/handleData.js'
|
||||
import { ref } from 'vue'
|
||||
const rolesOptions = ref([])
|
||||
const getRolesOption = async function() {
|
||||
const res = await getRoleAll()
|
||||
rolesOptions.value = dataToSelect(res.data, { label: 'name', value: 'id' })
|
||||
}
|
||||
// getRolesOption()
|
||||
const data = [
|
||||
{
|
||||
label: '用户账号',
|
||||
key: 'username',
|
||||
props: {
|
||||
placeholder: '请输入用户账号'
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '用户姓名',
|
||||
key: 'realname',
|
||||
props: {
|
||||
placeholder: '请输入用户姓名'
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '用户角色',
|
||||
type: 'select',
|
||||
key: 'roleId',
|
||||
props: {
|
||||
placeholder: '请选择用户角色',
|
||||
options: rolesOptions
|
||||
}
|
||||
}
|
||||
// {
|
||||
// label: '角色类型',
|
||||
// type: 'date',
|
||||
// key: 'date',
|
||||
// props: {
|
||||
// type: 'date'
|
||||
// }
|
||||
// }
|
||||
]
|
||||
|
||||
export default data
|
||||
|
||||
|
|
@ -1,69 +0,0 @@
|
|||
import { h } from 'vue'
|
||||
import TableImage from '@/components/DataTable/tools/Image.vue'
|
||||
import TableTags from '@/components/DataTable/tools/Tags.vue'
|
||||
|
||||
const table = {
|
||||
columns: [
|
||||
{
|
||||
type: 'selection'
|
||||
},
|
||||
{
|
||||
title: '用户编号',
|
||||
key: 'code',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: '头像',
|
||||
key: 'avatar',
|
||||
align: 'center',
|
||||
render(row) {
|
||||
return h(TableImage, {
|
||||
images: {
|
||||
width: 36,
|
||||
height: 36,
|
||||
src: row.avatar
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '用户账号',
|
||||
key: 'username',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: '用户姓名',
|
||||
key: 'realname',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: '角色',
|
||||
key: 'roleList',
|
||||
align: 'center',
|
||||
render(row) {
|
||||
return h(TableTags, {
|
||||
data: row.roleList,
|
||||
rowKey: 'name'
|
||||
})
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '部门',
|
||||
key: 'deptName',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: '创建时间',
|
||||
key: 'createTime',
|
||||
align: 'center',
|
||||
width: 160
|
||||
},
|
||||
{
|
||||
title: '更新时间',
|
||||
key: 'updateTime',
|
||||
align: 'center',
|
||||
width: 160
|
||||
}
|
||||
]
|
||||
}
|
||||
export default table
|
||||
Loading…
Reference in New Issue