feat: 从冻结 GoAdmin 源码重建 Sense 骨架 (#61)
This commit is contained in:
@@ -0,0 +1,333 @@
|
||||
<template>
|
||||
<BasicLayout>
|
||||
<template #wrapper>
|
||||
<el-card class="box-card">
|
||||
<el-form ref="queryForm" :model="queryParams" :inline="true" class="search-form">
|
||||
<el-form-item label="字典名称" prop="dictType">
|
||||
<el-select v-model="queryParams.dictType" size="small">
|
||||
<el-option
|
||||
v-for="item in typeOptions"
|
||||
:key="item.dictId"
|
||||
:label="item.dictName"
|
||||
:value="item.dictType"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="字典标签" prop="dictLabel">
|
||||
<el-input
|
||||
v-model="queryParams.dictLabel"
|
||||
placeholder="请输入字典标签"
|
||||
clearable
|
||||
size="small"
|
||||
@keyup.enter="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="状态" prop="status">
|
||||
<el-select v-model="queryParams.status" placeholder="数据状态" clearable size="small">
|
||||
<el-option
|
||||
v-for="dict in statusOptions"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" size="small" :icon="Search" @click="handleQuery">搜索</el-button>
|
||||
<el-button size="small" :icon="Refresh" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<div class="toolbar mb8">
|
||||
<el-button v-permisaction="['admin:sysDictData:add']" type="primary" size="small" :icon="Plus" @click="handleAdd">新增</el-button>
|
||||
<el-button v-permisaction="['admin:sysDictData:edit']" type="primary" size="small" :icon="Edit" :disabled="single" @click="handleUpdate">修改</el-button>
|
||||
<el-button v-permisaction="['admin:sysDictData:remove']" type="danger" size="small" :icon="Delete" :disabled="multiple" @click="handleDelete">删除</el-button>
|
||||
</div>
|
||||
|
||||
<el-table v-loading="loading" :data="dataList" border stripe @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="字典编码" width="80" align="center" prop="dictCode" />
|
||||
<el-table-column label="字典标签" align="center" prop="dictLabel" />
|
||||
<el-table-column label="字典键值" align="center" prop="dictValue" />
|
||||
<el-table-column label="字典排序" align="center" prop="dictSort" />
|
||||
<el-table-column label="状态" align="center" prop="status">
|
||||
<template #default="scope">
|
||||
<el-tag :type="parseInt(scope.row.status) === 2 ? 'success' : 'danger'" size="small" disable-transitions>
|
||||
{{ statusFormat(scope.row) }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="备注" align="center" prop="remark" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="创建时间" align="center" prop="createdAt" width="180">
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.createdAt) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||
<template #default="scope">
|
||||
<el-button v-permisaction="['admin:sysDictData:edit']" type="primary" link size="small" :icon="Edit" @click="handleUpdate(scope.row)">修改</el-button>
|
||||
<el-divider direction="vertical" />
|
||||
<el-button v-permisaction="['admin:sysDictData:remove']" type="danger" link size="small" :icon="Delete" @click="handleDelete(scope.row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<pagination
|
||||
v-show="total>0"
|
||||
v-model:current-page="queryParams.pageIndex"
|
||||
v-model:page-size="queryParams.pageSize"
|
||||
:total="total"
|
||||
@pagination="getList"
|
||||
/>
|
||||
|
||||
<!-- 添加或修改参数配置对话框 -->
|
||||
<el-dialog v-model="open" :title="title" width="500px" :close-on-click-modal="false">
|
||||
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
|
||||
<el-form-item label="字典类型">
|
||||
<el-input v-model="form.dictType" :disabled="true" />
|
||||
</el-form-item>
|
||||
<el-form-item label="数据标签" prop="dictLabel">
|
||||
<el-input v-model="form.dictLabel" placeholder="请输入数据标签" :disabled="isEdit" />
|
||||
</el-form-item>
|
||||
<el-form-item label="数据键值" prop="dictValue">
|
||||
<el-input v-model="form.dictValue" placeholder="请输入数据键值" :disabled="isEdit" />
|
||||
</el-form-item>
|
||||
<el-form-item label="显示排序" prop="dictSort">
|
||||
<el-input-number v-model="form.dictSort" controls-position="right" :min="0" />
|
||||
</el-form-item>
|
||||
<el-form-item label="状态" prop="status">
|
||||
<el-radio-group v-model="form.status">
|
||||
<el-radio
|
||||
v-for="dict in statusOptions"
|
||||
:key="dict.value"
|
||||
:label="dict.value"
|
||||
>{{ dict.label }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer><div class="dialog-footer">
|
||||
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
</div></template>
|
||||
</el-dialog>
|
||||
</el-card>
|
||||
</template>
|
||||
</BasicLayout>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { listData, getData, delData, addData, updateData, exportData } from '@/api/admin/dict/data'
|
||||
import { listType, getType } from '@/api/admin/dict/type'
|
||||
import { Search, Refresh, Plus, Edit, Delete } from '@element-plus/icons-vue'
|
||||
|
||||
export default {
|
||||
name: 'SysDictDataManage',
|
||||
setup() {
|
||||
return { Search, Refresh, Plus, Edit, Delete }
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 选中数组
|
||||
ids: [],
|
||||
// 非单个禁用
|
||||
single: true,
|
||||
// 非多个禁用
|
||||
multiple: true,
|
||||
// 总条数
|
||||
total: 0,
|
||||
// 字典表格数据
|
||||
dataList: [],
|
||||
// 默认字典类型
|
||||
defaultDictType: '',
|
||||
// 弹出层标题
|
||||
title: '',
|
||||
isEdit: false,
|
||||
// 是否显示弹出层
|
||||
open: false,
|
||||
// 状态数据字典
|
||||
statusOptions: [],
|
||||
// 类型数据字典
|
||||
typeOptions: [],
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageIndex: 1,
|
||||
pageSize: 10,
|
||||
dictName: undefined,
|
||||
dictType: undefined,
|
||||
status: undefined
|
||||
},
|
||||
// 表单参数
|
||||
form: {},
|
||||
// 表单校验
|
||||
rules: {
|
||||
dictLabel: [
|
||||
{ required: true, message: '数据标签不能为空', trigger: 'blur' }
|
||||
],
|
||||
dictValue: [
|
||||
{ required: true, message: '数据键值不能为空', trigger: 'blur' }
|
||||
],
|
||||
dictSort: [
|
||||
{ required: true, message: '数据顺序不能为空', trigger: 'blur' }
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
const dictId = this.$route.params && this.$route.params.dictId
|
||||
this.getType(dictId)
|
||||
this.getTypeList()
|
||||
this.getDicts('sys_normal_disable').then(response => {
|
||||
this.statusOptions = response.data
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
/** 查询字典类型详细 */
|
||||
getType(dictId) {
|
||||
getType(dictId).then(response => {
|
||||
this.queryParams.dictType = response.data.dictType
|
||||
this.defaultDictType = response.data.dictType
|
||||
this.getList()
|
||||
})
|
||||
},
|
||||
/** 查询字典类型列表 */
|
||||
getTypeList() {
|
||||
listType({ pageSize: 1000 }).then(response => {
|
||||
this.typeOptions = response.data.list
|
||||
})
|
||||
},
|
||||
/** 查询字典数据列表 */
|
||||
getList() {
|
||||
this.loading = true
|
||||
listData(this.queryParams).then(response => {
|
||||
this.dataList = response.data.list
|
||||
this.total = response.data.count
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
// 数据状态字典翻译
|
||||
statusFormat(row, column) {
|
||||
return this.selectDictLabel(this.statusOptions, row.status)
|
||||
},
|
||||
// 取消按钮
|
||||
cancel() {
|
||||
this.open = false
|
||||
this.reset()
|
||||
},
|
||||
// 表单重置
|
||||
reset() {
|
||||
this.form = {
|
||||
dictCode: undefined,
|
||||
dictLabel: undefined,
|
||||
dictValue: undefined,
|
||||
dictSort: 0,
|
||||
status: '2',
|
||||
remark: undefined
|
||||
}
|
||||
this.resetForm('form')
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
this.queryParams.pageIndex = 1
|
||||
this.getList()
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.resetForm('queryForm')
|
||||
this.queryParams.dictType = this.defaultDictType
|
||||
this.handleQuery()
|
||||
},
|
||||
/** 新增按钮操作 */
|
||||
handleAdd() {
|
||||
this.reset()
|
||||
this.open = true
|
||||
this.title = '添加字典数据'
|
||||
this.isEdit = false
|
||||
this.form.dictType = this.queryParams.dictType
|
||||
},
|
||||
// 多选框选中数据
|
||||
handleSelectionChange(selection) {
|
||||
this.ids = selection.map(item => item.dictCode)
|
||||
this.single = selection.length !== 1
|
||||
this.multiple = !selection.length
|
||||
},
|
||||
/** 修改按钮操作 */
|
||||
handleUpdate(row) {
|
||||
this.reset()
|
||||
const dictCode = row.dictCode || this.ids
|
||||
getData(dictCode).then(response => {
|
||||
this.form = response.data
|
||||
this.form.status = String(this.form.status)
|
||||
this.open = true
|
||||
this.title = '修改字典数据'
|
||||
this.isEdit = true
|
||||
})
|
||||
},
|
||||
/** 提交按钮 */
|
||||
submitForm: function() {
|
||||
this.$refs['form'].validate(valid => {
|
||||
if (valid) {
|
||||
this.form.status = parseInt(this.form.status)
|
||||
if (this.form.dictCode !== undefined) {
|
||||
updateData(this.form).then(response => {
|
||||
if (response.code === 200) {
|
||||
this.msgSuccess(response.msg)
|
||||
this.open = false
|
||||
this.getList()
|
||||
} else {
|
||||
this.msgError(response.msg)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
addData(this.form).then(response => {
|
||||
if (response.code === 200) {
|
||||
this.msgSuccess(response.msg)
|
||||
this.open = false
|
||||
this.getList()
|
||||
} else {
|
||||
this.msgError(response.msg)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
/** 删除按钮操作 */
|
||||
handleDelete(row) {
|
||||
const dictCodes = (row.dictCode && [row.dictCode]) || this.ids
|
||||
this.$confirm('是否确认删除字典编码为"' + dictCodes + '"的数据项?', '警告', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(function() {
|
||||
return delData({ 'ids': dictCodes })
|
||||
}).then((response) => {
|
||||
if (response.code === 200) {
|
||||
this.msgSuccess(response.msg)
|
||||
this.open = false
|
||||
this.getList()
|
||||
} else {
|
||||
this.msgError(response.msg)
|
||||
}
|
||||
}).catch(function() {})
|
||||
},
|
||||
/** 导出按钮操作 */
|
||||
handleExport() {
|
||||
const queryParams = this.queryParams
|
||||
this.$confirm('是否确认导出所有数据项?', '警告', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(function() {
|
||||
return exportData(queryParams)
|
||||
}).then(response => {
|
||||
this.download(response.msg)
|
||||
}).catch(function() {})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,322 @@
|
||||
<template>
|
||||
<BasicLayout>
|
||||
<template #wrapper>
|
||||
<el-card class="box-card">
|
||||
<el-form ref="queryForm" :model="queryParams" :inline="true" class="search-form">
|
||||
<el-form-item label="字典名称" prop="dictName">
|
||||
<el-input
|
||||
v-model="queryParams.dictName"
|
||||
placeholder="请输入字典名称"
|
||||
clearable
|
||||
size="small"
|
||||
@keyup.enter="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="字典类型" prop="dictType">
|
||||
<el-input
|
||||
v-model="queryParams.dictType"
|
||||
placeholder="请输入字典类型"
|
||||
clearable
|
||||
size="small"
|
||||
@keyup.enter="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="状态" prop="status">
|
||||
<el-select
|
||||
v-model="queryParams.status"
|
||||
placeholder="字典状态"
|
||||
clearable
|
||||
size="small"
|
||||
>
|
||||
<el-option
|
||||
v-for="dict in statusOptions"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
<el-button type="primary" size="small" :icon="Search" @click="handleQuery">搜索</el-button>
|
||||
<el-button size="small" :icon="Refresh" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<div class="toolbar mb8">
|
||||
<el-button v-permisaction="['admin:sysDictType:add']" type="primary" size="small" :icon="Plus" @click="handleAdd">新增</el-button>
|
||||
<el-button v-permisaction="['admin:sysDictType:edit']" type="primary" size="small" :icon="Edit" :disabled="single" @click="handleUpdate">修改</el-button>
|
||||
<el-button v-permisaction="['admin:sysDictType:remove']" type="danger" size="small" :icon="Delete" :disabled="multiple" @click="handleDelete">删除</el-button>
|
||||
<el-button v-permisaction="['admin:sysDictType:export']" size="small" :icon="Download" @click="handleExport">导出</el-button>
|
||||
</div>
|
||||
|
||||
<el-table v-loading="loading" :data="typeList" border stripe @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="字典编号" width="80" align="center" prop="id" />
|
||||
<el-table-column label="字典名称" align="center" prop="dictName" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="字典类型" align="center" :show-overflow-tooltip="true">
|
||||
<template #default="scope">
|
||||
<router-link :to="{name:'SysDictDataManage', params: {dictId:scope.row.id}}" class="link-type">
|
||||
<span>{{ scope.row.dictType }}</span>
|
||||
</router-link>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" align="center" prop="status">
|
||||
<template #default="scope">
|
||||
<el-tag :type="parseInt(scope.row.status) === 2 ? 'success' : 'danger'" size="small" disable-transitions>
|
||||
{{ statusFormat(scope.row) }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="备注" align="center" prop="remark" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="创建时间" align="center" prop="createdAt" width="180">
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.createdAt) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||
<template #default="scope">
|
||||
<el-button v-permisaction="['admin:sysDictType:edit']" type="primary" link size="small" :icon="Edit" @click="handleUpdate(scope.row)">修改</el-button>
|
||||
<el-divider direction="vertical" />
|
||||
<el-button v-permisaction="['admin:sysDictType:remove']" type="danger" link size="small" :icon="Delete" @click="handleDelete(scope.row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<pagination
|
||||
v-show="total>0"
|
||||
v-model:current-page="queryParams.pageIndex"
|
||||
v-model:page-size="queryParams.pageSize"
|
||||
:total="total"
|
||||
@pagination="getList"
|
||||
/>
|
||||
|
||||
<!-- 添加或修改参数配置对话框 -->
|
||||
<el-dialog v-model="open" :title="title" width="500px" :close-on-click-modal="false">
|
||||
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
|
||||
<el-form-item label="字典名称" prop="dictName">
|
||||
<el-input v-model="form.dictName" placeholder="请输入字典名称" :disabled="isEdit" />
|
||||
</el-form-item>
|
||||
<el-form-item label="字典类型" prop="dictType">
|
||||
<el-input v-model="form.dictType" placeholder="请输入字典类型" :disabled="isEdit" />
|
||||
</el-form-item>
|
||||
<el-form-item label="状态" prop="status">
|
||||
<el-radio-group v-model="form.status">
|
||||
<el-radio
|
||||
v-for="dict in statusOptions"
|
||||
:key="dict.value"
|
||||
:label="dict.value"
|
||||
>{{ dict.label }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer><div class="dialog-footer">
|
||||
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
</div></template>
|
||||
</el-dialog>
|
||||
</el-card>
|
||||
</template>
|
||||
</BasicLayout>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { listType, getType, delType, addType, updateType } from '@/api/admin/dict/type'
|
||||
import { formatJson } from '@/utils'
|
||||
import { Search, Refresh, Plus, Edit, Delete, Download } from '@element-plus/icons-vue'
|
||||
|
||||
export default {
|
||||
name: 'SysDictTypeManage',
|
||||
setup() {
|
||||
return { Search, Refresh, Plus, Edit, Delete, Download }
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 选中数组
|
||||
ids: [],
|
||||
// 非单个禁用
|
||||
single: true,
|
||||
// 非多个禁用
|
||||
multiple: true,
|
||||
// 总条数
|
||||
total: 0,
|
||||
// 字典表格数据
|
||||
typeList: [],
|
||||
// 弹出层标题
|
||||
title: '',
|
||||
isEdit: false,
|
||||
// 是否显示弹出层
|
||||
open: false,
|
||||
// 状态数据字典
|
||||
statusOptions: [],
|
||||
// 日期范围
|
||||
dateRange: [],
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageIndex: 1,
|
||||
pageSize: 10,
|
||||
dictName: undefined,
|
||||
dictType: undefined,
|
||||
status: undefined
|
||||
},
|
||||
// 表单参数
|
||||
form: {},
|
||||
// 表单校验
|
||||
rules: {
|
||||
dictName: [
|
||||
{ required: true, message: '字典名称不能为空', trigger: 'blur' }
|
||||
],
|
||||
dictType: [
|
||||
{ required: true, message: '字典类型不能为空', trigger: 'blur' }
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getList()
|
||||
this.getDicts('sys_normal_disable').then(response => {
|
||||
this.statusOptions = response.data
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
/** 查询字典类型列表 */
|
||||
getList() {
|
||||
this.loading = true
|
||||
listType(this.addDateRange(this.queryParams, this.dateRange)).then(response => {
|
||||
this.typeList = response.data.list
|
||||
this.total = response.data.count
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
// 字典状态字典翻译
|
||||
statusFormat(row, column) {
|
||||
return this.selectDictLabel(this.statusOptions, parseInt(row.status))
|
||||
},
|
||||
// 取消按钮
|
||||
cancel() {
|
||||
this.open = false
|
||||
this.reset()
|
||||
},
|
||||
// 表单重置
|
||||
reset() {
|
||||
this.form = {
|
||||
id: undefined,
|
||||
dictName: undefined,
|
||||
dictType: undefined,
|
||||
status: '2',
|
||||
remark: undefined
|
||||
}
|
||||
this.resetForm('form')
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
this.queryParams.pageIndex = 1
|
||||
this.getList()
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.dateRange = []
|
||||
this.resetForm('queryForm')
|
||||
this.handleQuery()
|
||||
},
|
||||
/** 新增按钮操作 */
|
||||
handleAdd() {
|
||||
this.reset()
|
||||
this.open = true
|
||||
this.title = '添加字典类型'
|
||||
this.isEdit = false
|
||||
},
|
||||
// 多选框选中数据
|
||||
handleSelectionChange(selection) {
|
||||
this.ids = selection.map(item => item.id)
|
||||
this.single = selection.length !== 1
|
||||
this.multiple = !selection.length
|
||||
},
|
||||
/** 修改按钮操作 */
|
||||
handleUpdate(row) {
|
||||
this.reset()
|
||||
const dictId = row.id || this.ids
|
||||
getType(dictId).then(response => {
|
||||
this.form = response.data
|
||||
this.form.status = String(this.form.status)
|
||||
this.open = true
|
||||
this.title = '修改字典类型'
|
||||
this.isEdit = true
|
||||
})
|
||||
},
|
||||
/** 提交按钮 */
|
||||
submitForm: function() {
|
||||
this.$refs['form'].validate(valid => {
|
||||
if (valid) {
|
||||
this.form.status = parseInt(this.form.status)
|
||||
if (this.form.id !== undefined) {
|
||||
updateType(this.form).then(response => {
|
||||
if (response.code === 200) {
|
||||
this.msgSuccess(response.msg)
|
||||
this.open = false
|
||||
this.getList()
|
||||
} else {
|
||||
this.msgError(response.msg)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
addType(this.form).then(response => {
|
||||
if (response.code === 200) {
|
||||
this.msgSuccess(response.msg)
|
||||
this.open = false
|
||||
this.getList()
|
||||
} else {
|
||||
this.msgError(response.msg)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
/** 删除按钮操作 */
|
||||
handleDelete(row) {
|
||||
const dictIds = (row.id && [row.id]) || this.ids
|
||||
this.$confirm('是否确认删除字典编号为"' + dictIds + '"的数据项?', '警告', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(function() {
|
||||
return delType({ 'ids': dictIds })
|
||||
}).then(() => {
|
||||
this.getList()
|
||||
this.msgSuccess('删除成功')
|
||||
}).catch(function() {})
|
||||
},
|
||||
/** 导出按钮操作 */
|
||||
handleExport() {
|
||||
// const queryParams = this.queryParams
|
||||
this.$confirm('是否确认导出所有类型数据项?', '警告', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
this.downloadLoading = true
|
||||
import('@/vendor/Export2Excel').then(excel => {
|
||||
const tHeader = ['字典编号', '字典名称', '字典类型', '状态', '备注']
|
||||
const filterVal = ['id', 'dictName', 'dictType', 'status', 'remark']
|
||||
const list = this.typeList
|
||||
const data = formatJson(filterVal, list)
|
||||
excel.export_json_to_excel({
|
||||
header: tHeader,
|
||||
data,
|
||||
filename: '字典管理',
|
||||
autoWidth: true, // Optional
|
||||
bookType: 'xlsx' // Optional
|
||||
})
|
||||
this.downloadLoading = false
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,426 @@
|
||||
|
||||
<template>
|
||||
<BasicLayout>
|
||||
<template #wrapper>
|
||||
<el-card class="box-card">
|
||||
<el-form ref="queryForm" :model="queryParams" :inline="true" class="search-form">
|
||||
<el-form-item label="标题" prop="title">
|
||||
<el-input
|
||||
v-model="queryParams.title"
|
||||
placeholder="请输入标题"
|
||||
clearable
|
||||
size="small"
|
||||
@keyup.enter="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="地址" prop="path">
|
||||
<el-input
|
||||
v-model="queryParams.path"
|
||||
placeholder="请输入地址"
|
||||
clearable
|
||||
size="small"
|
||||
@keyup.enter="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="Method" prop="action">
|
||||
<el-select
|
||||
v-model="queryParams.action"
|
||||
placeholder="请选择Method"
|
||||
clearable
|
||||
size="small"
|
||||
>
|
||||
<el-option value="GET">GET</el-option>
|
||||
<el-option value="POST">POST</el-option>
|
||||
<el-option value="PUT">PUT</el-option>
|
||||
<el-option value="DELETE">DELETE</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="类型" prop="type">
|
||||
<el-select
|
||||
v-model="queryParams.type"
|
||||
placeholder="请选择类型"
|
||||
clearable
|
||||
size="small"
|
||||
>
|
||||
<el-option value="SYS">SYS</el-option>
|
||||
<el-option value="BUS">BUS</el-option>
|
||||
<el-option value="暂无">暂无</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" size="small" :icon="Search" @click="handleQuery">搜索</el-button>
|
||||
<el-button size="small" :icon="Refresh" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
:data="sysapiList"
|
||||
border
|
||||
stripe
|
||||
@selection-change="handleSelectionChange"
|
||||
@sort-change="handleSortChang"
|
||||
>
|
||||
<el-table-column
|
||||
label="标题"
|
||||
header-align="center"
|
||||
align="left"
|
||||
prop="title"
|
||||
fixed="left"
|
||||
sortable="custom"
|
||||
width="260px"
|
||||
:show-overflow-tooltip="true"
|
||||
>
|
||||
<template #default="scope">
|
||||
<span v-if="scope.row.type=='SYS' && scope.row.title!=''"><el-tag type="success">{{ '['+scope.row.type +'] '+ scope.row.title }}</el-tag></span>
|
||||
<span v-if="scope.row.type!='SYS' && scope.row.title!=''"><el-tag type="">{{ '['+scope.row.type +'] '+scope.row.title }}</el-tag></span>
|
||||
<span v-if="scope.row.title==''"><el-tag type="danger">暂无</el-tag></span>
|
||||
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
label="Request Info"
|
||||
header-align="center"
|
||||
align="left"
|
||||
prop="path"
|
||||
sortable="custom"
|
||||
:show-overflow-tooltip="true"
|
||||
>
|
||||
<!-- <template v-slot="scope">
|
||||
<span>{{ "["+scope.row.action +"] "+ scope.row.path }}</span>
|
||||
</template> -->
|
||||
<template #default="scope">
|
||||
<el-popover trigger="hover" placement="top">
|
||||
<p><span v-if="scope.row.type=='SYS' && scope.row.title!=''"><el-tag type="success">{{ '['+scope.row.type +'] '+ scope.row.title }}</el-tag></span>
|
||||
<span v-if="scope.row.type!='SYS' && scope.row.title!=''"><el-tag type="">{{ '['+scope.row.type +'] '+scope.row.title }}</el-tag></span>
|
||||
<span v-if="scope.row.title==''"><el-tag type="danger">暂无</el-tag></span>
|
||||
</p>
|
||||
<p>Handle: {{ scope.row.handle }}</p>
|
||||
<p>Method:
|
||||
<el-tag v-if="scope.row.action=='GET'">{{ scope.row.action }}</el-tag>
|
||||
<el-tag v-if="scope.row.action=='POST'" type="success">{{ scope.row.action }}</el-tag>
|
||||
<el-tag v-if="scope.row.action=='PUT'" type="warning">{{ scope.row.action }}</el-tag>
|
||||
<el-tag v-if="scope.row.action=='DELETE'" type="danger">{{ scope.row.action }}</el-tag>
|
||||
</p>
|
||||
<p>接口类型: {{ scope.row.type }}</p>
|
||||
<template #reference><div class="name-wrapper">
|
||||
<el-tag v-if="scope.row.action=='GET'">{{ scope.row.action }}</el-tag>
|
||||
<el-tag v-if="scope.row.action=='POST'" type="success">{{ scope.row.action }}</el-tag>
|
||||
<el-tag v-if="scope.row.action=='PUT'" type="warning">{{ scope.row.action }}</el-tag>
|
||||
<el-tag v-if="scope.row.action=='DELETE'" type="danger">{{ scope.row.action }}</el-tag>
|
||||
{{ scope.row.path }}
|
||||
</div></template>
|
||||
</el-popover>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
label="创建时间"
|
||||
align="center"
|
||||
prop="createdAt"
|
||||
width="155px"
|
||||
sortable="custom"
|
||||
>
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.createdAt) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
label="操作"
|
||||
align="center"
|
||||
width="80px"
|
||||
class-name="small-padding fixed-width"
|
||||
>
|
||||
<template #default="scope">
|
||||
<el-button v-permisaction="['admin:sysApi:edit']" type="primary" link size="small" :icon="Edit" @click="handleUpdate(scope.row)">修改</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<pagination
|
||||
v-show="total>0"
|
||||
v-model:current-page="queryParams.pageIndex"
|
||||
v-model:page-size="queryParams.pageSize"
|
||||
:total="total"
|
||||
@pagination="getList"
|
||||
/>
|
||||
|
||||
<!-- 添加或修改对话框 -->
|
||||
<el-drawer
|
||||
ref="drawer"
|
||||
v-model="open"
|
||||
:title="title"
|
||||
:before-close="cancel"
|
||||
direction="rtl"
|
||||
custom-class="demo-drawer"
|
||||
>
|
||||
<div class="demo-drawer__content">
|
||||
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
|
||||
|
||||
<el-form-item label="Handle" prop="handle">
|
||||
<el-input
|
||||
v-model="form.handle"
|
||||
placeholder="handle"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="标题" prop="title">
|
||||
<el-input
|
||||
v-model="form.title"
|
||||
placeholder="标题"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="类型" prop="type">
|
||||
<el-select
|
||||
v-model="form.type"
|
||||
placeholder="请选择类型"
|
||||
clearable
|
||||
size="small"
|
||||
@keyup.enter="handleQuery"
|
||||
>
|
||||
<el-option value="SYS">SYS</el-option>
|
||||
<el-option value="BUS">BUS</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="Method" prop="action">
|
||||
<el-select
|
||||
v-model="form.action"
|
||||
placeholder="请选择方式"
|
||||
clearable
|
||||
size="small"
|
||||
@keyup.enter="handleQuery"
|
||||
>
|
||||
<el-option value="GET">GET</el-option>
|
||||
<el-option value="POST">POST</el-option>
|
||||
<el-option value="PUT">PUT</el-option>
|
||||
<el-option value="DELETE">DELETE</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="地址" prop="path">
|
||||
<el-input
|
||||
v-model="form.path"
|
||||
:disabled="isEdit"
|
||||
placeholder="地址"
|
||||
/>
|
||||
</el-form-item>
|
||||
|
||||
</el-form>
|
||||
<div class="demo-drawer__footer">
|
||||
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</el-drawer>
|
||||
|
||||
</el-card>
|
||||
</template>
|
||||
</BasicLayout>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { addSysApi, delSysApi, getSysApi, listSysApi, updateSysApi } from '@/api/admin/sys-api'
|
||||
import { Search, Refresh, Edit } from '@element-plus/icons-vue'
|
||||
|
||||
export default {
|
||||
name: 'SysApiManage',
|
||||
components: {
|
||||
},
|
||||
setup() {
|
||||
return { Search, Refresh, Edit }
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
dialog: false,
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 选中数组
|
||||
ids: [],
|
||||
// 非单个禁用
|
||||
single: true,
|
||||
// 非多个禁用
|
||||
multiple: true,
|
||||
// 总条数
|
||||
total: 0,
|
||||
// 弹出层标题
|
||||
title: '',
|
||||
// 是否显示弹出层
|
||||
open: false,
|
||||
isEdit: false,
|
||||
// 类型数据字典
|
||||
typeOptions: [],
|
||||
sysapiList: [],
|
||||
dateRange: [],
|
||||
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageIndex: 1,
|
||||
pageSize: 10,
|
||||
name: undefined,
|
||||
title: undefined,
|
||||
path: undefined,
|
||||
type: undefined,
|
||||
action: undefined,
|
||||
parentId: undefined
|
||||
|
||||
},
|
||||
// 表单参数
|
||||
form: {
|
||||
},
|
||||
// 表单校验
|
||||
rules: {
|
||||
title: [{ required: true, message: '标题不能为空', trigger: 'blur' }],
|
||||
path: [{ required: true, message: '地址不能为空', trigger: 'blur' }],
|
||||
action: [{ required: true, message: '类型不能为空', trigger: 'blur' }],
|
||||
parentId: [{ required: true, message: '按钮id不能为空', trigger: 'blur' }]
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getList()
|
||||
},
|
||||
methods: {
|
||||
handleClose(done) {
|
||||
if (this.loading) {
|
||||
return
|
||||
}
|
||||
done()
|
||||
},
|
||||
/** 查询参数列表 */
|
||||
getList() {
|
||||
this.loading = true
|
||||
listSysApi(this.queryParams).then(response => {
|
||||
this.sysapiList = response.data.list
|
||||
this.total = response.data.count
|
||||
this.loading = false
|
||||
}
|
||||
)
|
||||
},
|
||||
// 取消按钮
|
||||
cancel() {
|
||||
this.open = false
|
||||
this.reset()
|
||||
},
|
||||
// 表单重置
|
||||
reset() {
|
||||
this.form = {
|
||||
id: undefined,
|
||||
name: undefined,
|
||||
title: undefined,
|
||||
path: undefined,
|
||||
paths: undefined,
|
||||
action: undefined,
|
||||
parentId: undefined,
|
||||
sort: undefined
|
||||
}
|
||||
this.resetForm('form')
|
||||
},
|
||||
parentIdFormat(row) {
|
||||
return this.selectItemsLabel(this.parentIdOptions, row.parentId)
|
||||
},
|
||||
// 文件
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
this.queryParams.pageIndex = 1
|
||||
this.getList()
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.dateRange = []
|
||||
this.resetForm('queryForm')
|
||||
this.handleQuery()
|
||||
},
|
||||
/** 新增按钮操作 */
|
||||
handleAdd() {
|
||||
this.reset()
|
||||
this.open = true
|
||||
this.title = '添加接口管理'
|
||||
this.isEdit = false
|
||||
},
|
||||
/** 排序回调函数 */
|
||||
handleSortChang(column, prop, order) {
|
||||
prop = column.prop
|
||||
order = column.order
|
||||
if (this.order !== '' && this.order !== prop + 'Order') {
|
||||
this.queryParams[this.order] = undefined
|
||||
}
|
||||
if (order === 'descending') {
|
||||
this.queryParams[prop + 'Order'] = 'desc'
|
||||
this.order = prop + 'Order'
|
||||
} else if (order === 'ascending') {
|
||||
this.queryParams[prop + 'Order'] = 'asc'
|
||||
this.order = prop + 'Order'
|
||||
} else {
|
||||
this.queryParams[prop + 'Order'] = undefined
|
||||
}
|
||||
this.getList()
|
||||
},
|
||||
// 多选框选中数据
|
||||
handleSelectionChange(selection) {
|
||||
this.ids = selection.map(item => item.id)
|
||||
this.single = selection.length !== 1
|
||||
this.multiple = !selection.length
|
||||
},
|
||||
/** 修改按钮操作 */
|
||||
handleUpdate(row) {
|
||||
this.reset()
|
||||
const id =
|
||||
row.id || this.ids
|
||||
getSysApi(id).then(response => {
|
||||
this.form = response.data
|
||||
this.open = true
|
||||
this.title = '修改接口管理'
|
||||
this.isEdit = true
|
||||
})
|
||||
},
|
||||
/** 提交按钮 */
|
||||
submitForm: function() {
|
||||
this.$refs['form'].validate(valid => {
|
||||
if (valid) {
|
||||
if (this.form.id !== undefined) {
|
||||
updateSysApi(this.form).then(response => {
|
||||
if (response.code === 200) {
|
||||
this.msgSuccess(response.msg)
|
||||
this.open = false
|
||||
this.getList()
|
||||
} else {
|
||||
this.msgError(response.msg)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
addSysApi(this.form).then(response => {
|
||||
if (response.code === 200) {
|
||||
this.msgSuccess(response.msg)
|
||||
this.open = false
|
||||
this.getList()
|
||||
} else {
|
||||
this.msgError(response.msg)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
/** 删除按钮操作 */
|
||||
handleDelete(row) {
|
||||
var Ids = (row.id && [row.id]) || this.ids
|
||||
|
||||
this.$confirm('是否确认删除编号为"' + Ids + '"的数据项?', '警告', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(function() {
|
||||
return delSysApi({ 'ids': Ids })
|
||||
}).then((response) => {
|
||||
if (response.code === 200) {
|
||||
this.msgSuccess(response.msg)
|
||||
this.open = false
|
||||
this.getList()
|
||||
} else {
|
||||
this.msgError(response.msg)
|
||||
}
|
||||
}).catch(function() {})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,432 @@
|
||||
<template>
|
||||
<BasicLayout>
|
||||
<template #wrapper>
|
||||
<el-card class="box-card">
|
||||
<el-form ref="queryForm" :model="queryParams" :inline="true" label-width="48px">
|
||||
<el-form-item label="名称" prop="configName">
|
||||
<el-input
|
||||
v-model="queryParams.configName"
|
||||
placeholder="请输入参数名称"
|
||||
clearable
|
||||
size="small"
|
||||
style="width: 160px"
|
||||
@keyup.enter="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="键名" prop="configKey">
|
||||
<el-input
|
||||
v-model="queryParams.configKey"
|
||||
placeholder="请输入参数键名"
|
||||
clearable
|
||||
size="small"
|
||||
style="width: 160px"
|
||||
@keyup.enter="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="内置" prop="configType">
|
||||
<el-select v-model="queryParams.configType" placeholder="系统内置" clearable size="small">
|
||||
<el-option
|
||||
v-for="dict in typeOptions"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" size="mini" @click="handleQuery">搜索</el-button>
|
||||
<el-button size="mini" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
v-permisaction="['admin:sysConfig:add']"
|
||||
type="primary"
|
||||
|
||||
size="mini"
|
||||
@click="handleAdd"
|
||||
>新增</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
v-permisaction="['admin:sysConfig:edit']"
|
||||
type="success"
|
||||
|
||||
size="mini"
|
||||
:disabled="single"
|
||||
@click="handleUpdate"
|
||||
>修改</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
v-permisaction="['admin:sysConfig:remove']"
|
||||
type="danger"
|
||||
|
||||
size="mini"
|
||||
:disabled="multiple"
|
||||
@click="handleDelete"
|
||||
>删除</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
v-permisaction="['admin:sysConfig:export']"
|
||||
type="warning"
|
||||
|
||||
size="mini"
|
||||
@click="handleExport"
|
||||
>导出</el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
:data="configList"
|
||||
border
|
||||
@selection-change="handleSelectionChange"
|
||||
@sort-change="handleSortChang"
|
||||
>
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column
|
||||
label="编码"
|
||||
sortable="custom"
|
||||
width="75"
|
||||
prop="id"
|
||||
/>
|
||||
<el-table-column
|
||||
label="名称"
|
||||
sortable="custom"
|
||||
prop="configName"
|
||||
:show-overflow-tooltip="true"
|
||||
/>
|
||||
<el-table-column
|
||||
label="键名"
|
||||
sortable="custom"
|
||||
prop="configKey"
|
||||
>
|
||||
<template #default="scope">
|
||||
<el-popover trigger="hover" placement="top">
|
||||
<p>键值: {{ scope.row.configValue }}</p>
|
||||
<p>UI参数: <el-tag v-if="scope.row.isFrontend=='2'">否</el-tag>
|
||||
<el-tag v-if="scope.row.isFrontend=='1'" type="success">是</el-tag>
|
||||
</p>
|
||||
<template #reference><div class="name-wrapper">
|
||||
{{ scope.row.configKey }}
|
||||
</div></template>
|
||||
</el-popover>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
label="内置"
|
||||
sortable="custom"
|
||||
prop="configType"
|
||||
:formatter="typeFormat"
|
||||
width="80"
|
||||
/>
|
||||
<el-table-column
|
||||
label="备注"
|
||||
prop="remark"
|
||||
:show-overflow-tooltip="true"
|
||||
/>
|
||||
<el-table-column
|
||||
label="创建时间"
|
||||
sortable="custom"
|
||||
prop="createdAt"
|
||||
width="160"
|
||||
>
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.createdAt) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
label="操作"
|
||||
class-name="small-padding fixed-width"
|
||||
width="120"
|
||||
>
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
v-permisaction="['admin:sysConfig:edit']"
|
||||
size="mini"
|
||||
type="text"
|
||||
|
||||
@click="handleUpdate(scope.row)"
|
||||
>修改</el-button>
|
||||
<el-button
|
||||
v-permisaction="['admin:sysConfig:remove']"
|
||||
size="mini"
|
||||
type="text"
|
||||
|
||||
@click="handleDelete(scope.row)"
|
||||
>删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<pagination
|
||||
v-show="total>0"
|
||||
v-model:current-page="queryParams.pageIndex"
|
||||
v-model:page-size="queryParams.pageSize"
|
||||
:total="total"
|
||||
@pagination="getList"
|
||||
/>
|
||||
|
||||
<!-- 添加或修改参数配置对话框 -->
|
||||
<el-dialog v-model="open" :title="title" width="500px" :close-on-click-modal="false">
|
||||
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
|
||||
<el-form-item label="参数名称" prop="configName">
|
||||
<el-input v-model="form.configName" placeholder="请输入参数名称" :disabled="isEdit" />
|
||||
</el-form-item>
|
||||
<el-form-item label="参数键名" prop="configKey">
|
||||
<el-input v-model="form.configKey" placeholder="请输入参数键名" :disabled="isEdit" />
|
||||
</el-form-item>
|
||||
<el-form-item label="参数键值" prop="configValue">
|
||||
<el-input v-model="form.configValue" placeholder="请输入参数键值" />
|
||||
</el-form-item>
|
||||
<el-form-item label="系统内置" prop="configType">
|
||||
<el-radio-group v-model="form.configType">
|
||||
<el-radio
|
||||
v-for="dict in typeOptions"
|
||||
:key="dict.value"
|
||||
:label="dict.value"
|
||||
>{{ dict.label }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="前台显示" prop="isFrontend">
|
||||
<el-select v-model="form.isFrontend" placeholder="是否前台显示" clearable size="small">
|
||||
<el-option label="是" value="1" />
|
||||
<el-option label="否" value="2" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer><div class="dialog-footer">
|
||||
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
</div></template>
|
||||
</el-dialog>
|
||||
</el-card>
|
||||
</template>
|
||||
</BasicLayout>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { listConfig, getConfig, delConfig, addConfig, updateConfig } from '@/api/admin/sys-config'
|
||||
import { formatJson } from '@/utils'
|
||||
|
||||
export default {
|
||||
name: 'SysConfigManage',
|
||||
data() {
|
||||
return {
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 选中数组
|
||||
ids: [],
|
||||
// 非单个禁用
|
||||
single: true,
|
||||
// 非多个禁用
|
||||
multiple: true,
|
||||
// 总条数
|
||||
total: 0,
|
||||
// 参数表格数据
|
||||
configList: [],
|
||||
// 排序字段
|
||||
order: 'createdAtOrder',
|
||||
// 弹出层标题
|
||||
title: '',
|
||||
isEdit: false,
|
||||
// 是否显示弹出层
|
||||
open: false,
|
||||
// 类型数据字典
|
||||
typeOptions: [],
|
||||
// 日期范围
|
||||
dateRange: [],
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageIndex: 1,
|
||||
pageSize: 10,
|
||||
configName: undefined,
|
||||
configKey: undefined,
|
||||
configType: undefined,
|
||||
createdAtOrder: 'desc'
|
||||
},
|
||||
// 表单参数
|
||||
form: {},
|
||||
// 表单校验
|
||||
rules: {
|
||||
configName: [{ required: true, message: '参数名称不能为空', trigger: 'blur' }],
|
||||
configKey: [{ required: true, message: '参数键名不能为空', trigger: 'blur' }],
|
||||
configValue: [{ required: true, message: '参数键值不能为空', trigger: 'blur' }],
|
||||
isFrontend: [{ required: true, message: '是否前台显示不能为空', trigger: 'blur' }]
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getList()
|
||||
this.getDicts('sys_yes_no').then(response => {
|
||||
this.typeOptions = response.data
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
/** 查询参数列表 */
|
||||
getList() {
|
||||
this.loading = true
|
||||
listConfig(this.addDateRange(this.queryParams, this.dateRange)).then(response => {
|
||||
this.configList = response.data.list
|
||||
this.total = response.data.count
|
||||
this.loading = false
|
||||
}
|
||||
)
|
||||
},
|
||||
// 参数系统内置字典翻译
|
||||
typeFormat(row, column) {
|
||||
return this.selectDictLabel(this.typeOptions, row.configType)
|
||||
},
|
||||
// 取消按钮
|
||||
cancel() {
|
||||
this.open = false
|
||||
this.reset()
|
||||
},
|
||||
// 表单重置
|
||||
reset() {
|
||||
this.form = {
|
||||
id: undefined,
|
||||
configName: undefined,
|
||||
configKey: undefined,
|
||||
configValue: undefined,
|
||||
configType: 'Y',
|
||||
isFrontend: '1',
|
||||
remark: undefined
|
||||
}
|
||||
this.resetForm('form')
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
this.queryParams.pageIndex = 1
|
||||
this.getList()
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.dateRange = []
|
||||
this.resetForm('queryForm')
|
||||
this.queryParams['createdAtOrderOrder'] = 'desc'
|
||||
this.handleQuery()
|
||||
},
|
||||
/** 新增按钮操作 */
|
||||
handleAdd() {
|
||||
this.reset()
|
||||
this.open = true
|
||||
this.title = '添加参数'
|
||||
this.isEdit = false
|
||||
},
|
||||
handleSortChang(column, prop, order) {
|
||||
prop = column.prop
|
||||
order = column.order
|
||||
if (this.order !== '' && this.order !== prop + 'Order') {
|
||||
this.queryParams[this.order] = undefined
|
||||
}
|
||||
if (order === 'descending') {
|
||||
this.queryParams[prop + 'Order'] = 'desc'
|
||||
this.order = prop + 'Order'
|
||||
} else if (order === 'ascending') {
|
||||
this.queryParams[prop + 'Order'] = 'asc'
|
||||
this.order = prop + 'Order'
|
||||
} else {
|
||||
this.queryParams[prop + 'Order'] = undefined
|
||||
}
|
||||
this.getList()
|
||||
},
|
||||
// 多选框选中数据
|
||||
handleSelectionChange(selection) {
|
||||
this.ids = selection.map(item => item.id)
|
||||
this.single = selection.length !== 1
|
||||
this.multiple = !selection.length
|
||||
},
|
||||
/** 修改按钮操作 */
|
||||
handleUpdate(row) {
|
||||
this.reset()
|
||||
const ID = row.id || this.ids
|
||||
getConfig(ID).then(response => {
|
||||
this.form = response.data
|
||||
this.open = true
|
||||
this.title = '修改参数'
|
||||
this.isEdit = true
|
||||
})
|
||||
},
|
||||
/** 提交按钮 */
|
||||
submitForm: function() {
|
||||
this.$refs['form'].validate(valid => {
|
||||
if (valid) {
|
||||
if (this.form.id !== undefined) {
|
||||
updateConfig(this.form).then(response => {
|
||||
if (response.code === 200) {
|
||||
this.msgSuccess(response.msg)
|
||||
this.open = false
|
||||
this.getList()
|
||||
} else {
|
||||
this.msgError(response.msg)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
addConfig(this.form).then(response => {
|
||||
if (response.code === 200) {
|
||||
this.msgSuccess(response.msg)
|
||||
this.open = false
|
||||
this.getList()
|
||||
} else {
|
||||
this.msgError(response.msg)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
/** 删除按钮操作 */
|
||||
handleDelete(row) {
|
||||
const Ids = (row.id && [row.id]) || this.ids
|
||||
this.$confirm('是否确认删除参数编号为"' + Ids + '"的数据项?', '警告', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(function() {
|
||||
return delConfig({ 'ids': Ids })
|
||||
}).then((response) => {
|
||||
if (response.code === 200) {
|
||||
this.msgSuccess(response.msg)
|
||||
this.open = false
|
||||
this.getList()
|
||||
} else {
|
||||
this.msgError(response.msg)
|
||||
}
|
||||
}).catch(function() {})
|
||||
},
|
||||
/** 导出按钮操作 */
|
||||
handleExport() {
|
||||
// const queryParams = this.queryParams
|
||||
this.$confirm('是否确认导出所有参数数据项?', '警告', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
this.downloadLoading = true
|
||||
import('@/vendor/Export2Excel').then(excel => {
|
||||
const tHeader = ['参数主键', '参数名称', '参数键名', '参数键值', '备注', '创建时间']
|
||||
const filterVal = ['configId', 'configName', 'configKey', 'configValue', 'remark', 'createdAt']
|
||||
const list = this.configList
|
||||
const data = formatJson(filterVal, list)
|
||||
excel.export_json_to_excel({
|
||||
header: tHeader,
|
||||
data,
|
||||
filename: '参数设置',
|
||||
autoWidth: true, // Optional
|
||||
bookType: 'xlsx' // Optional
|
||||
})
|
||||
this.downloadLoading = false
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,604 @@
|
||||
<template>
|
||||
<BasicLayout>
|
||||
<template #wrapper>
|
||||
<div class="sys-config-set">
|
||||
|
||||
<div class="config-wrapper">
|
||||
|
||||
<!-- ── 左侧导航 ── -->
|
||||
<div class="config-sidebar">
|
||||
<div class="sidebar-header">
|
||||
<div class="sidebar-icon-box">
|
||||
<el-icon :size="18" color="#1677ff"><Setting /></el-icon>
|
||||
</div>
|
||||
<div>
|
||||
<p class="sidebar-header__title">系统配置</p>
|
||||
<p class="sidebar-header__sub">基础信息与外观设置</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-divider" />
|
||||
<div
|
||||
v-for="(item, idx) in navItems"
|
||||
:key="idx"
|
||||
class="nav-item"
|
||||
:class="{ 'is-active': activeSection === idx }"
|
||||
@click="activeSection = idx"
|
||||
>
|
||||
<div class="nav-item__icon-wrap">
|
||||
<el-icon :size="15"><component :is="item.icon" /></el-icon>
|
||||
</div>
|
||||
<div class="nav-item__text">
|
||||
<span class="nav-item__label">{{ item.label }}</span>
|
||||
<span class="nav-item__sub">{{ item.sub }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ── 右侧主内容 ── -->
|
||||
<div class="config-main">
|
||||
|
||||
<!-- 基础信息 -->
|
||||
<transition name="fade-slide" mode="out-in">
|
||||
<div v-if="activeSection === 0" key="basic" class="config-section">
|
||||
<div class="section-head">
|
||||
<div class="section-head__icon-wrap">
|
||||
<el-icon :size="16" color="#1677ff"><OfficeBuilding /></el-icon>
|
||||
</div>
|
||||
<div>
|
||||
<p class="section-head__title">系统基础信息</p>
|
||||
<p class="section-head__desc">配置系统名称、Logo 及用户默认密码</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="section-body">
|
||||
<!-- Logo -->
|
||||
<div class="logo-zone">
|
||||
<div class="logo-preview">
|
||||
<img v-if="form.sys_app_logo" :src="form.sys_app_logo" alt="logo" class="logo-img">
|
||||
<div v-else class="logo-empty">
|
||||
<el-icon :size="24" color="#c0c4cc"><Picture /></el-icon>
|
||||
<span>暂无 Logo</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="logo-meta">
|
||||
<p class="logo-meta__name">系统 Logo</p>
|
||||
<p class="logo-meta__hint">推荐 200×200,支持 JPG / PNG,大小不超过 2MB</p>
|
||||
<el-upload
|
||||
:headers="headers"
|
||||
:file-list="sys_app_logofileList"
|
||||
:action="sys_app_logoAction"
|
||||
:before-upload="sys_app_logoBeforeUpload"
|
||||
:show-file-list="false"
|
||||
:on-success="uploadSuccess"
|
||||
>
|
||||
<el-button size="small" plain type="primary">
|
||||
<el-icon style="margin-right:4px"><Upload /></el-icon>上传图片
|
||||
</el-button>
|
||||
</el-upload>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<el-divider style="margin: 16px 0" />
|
||||
|
||||
<el-form ref="form" :model="form" :rules="rules" label-position="top">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="系统名称" prop="sys_app_name">
|
||||
<el-input v-model="form.sys_app_name" placeholder="请输入系统名称" clearable>
|
||||
<template #prefix><el-icon><OfficeBuilding /></el-icon></template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="用户初始密码" prop="sys_user_initPassword">
|
||||
<el-input v-model="form.sys_user_initPassword" placeholder="请输入初始密码" clearable show-password>
|
||||
<template #prefix><el-icon><Lock /></el-icon></template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 外观设置 -->
|
||||
<div v-else-if="activeSection === 1" key="theme" class="config-section">
|
||||
<div class="section-head">
|
||||
<div class="section-head__icon-wrap">
|
||||
<el-icon :size="16" color="#1677ff"><Brush /></el-icon>
|
||||
</div>
|
||||
<div>
|
||||
<p class="section-head__title">外观设置</p>
|
||||
<p class="section-head__desc">调整皮肤样式与侧栏主题风格</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="section-body">
|
||||
<el-form label-position="top">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="皮肤样式">
|
||||
<el-select v-model="form.sys_index_skinName" placeholder="请选择皮肤样式" style="width:100%">
|
||||
<el-option v-for="(item, i) in sys_index_skinNameOptions" :key="i" :label="item.label" :value="item.value" :disabled="item.disabled" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="侧栏主题">
|
||||
<el-select v-model="form.sys_index_sideTheme" placeholder="请选择侧栏主题" style="width:100%">
|
||||
<el-option v-for="(item, i) in sys_index_sideThemeOptions" :key="i" :label="item.label" :value="item.value" :disabled="item.disabled" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
|
||||
<p class="theme-label">点击快速切换主题</p>
|
||||
<div class="theme-row">
|
||||
<div
|
||||
class="theme-card"
|
||||
:class="{ 'is-active': form.sys_index_sideTheme === 'theme-dark' }"
|
||||
@click="form.sys_index_sideTheme = 'theme-dark'"
|
||||
>
|
||||
<div class="tc-preview tc-preview--dark">
|
||||
<div class="tc-sidebar" />
|
||||
<div class="tc-body">
|
||||
<div class="tc-topbar" />
|
||||
<div class="tc-content" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="tc-label">
|
||||
<span>深色主题</span>
|
||||
<el-icon v-if="form.sys_index_sideTheme === 'theme-dark'" color="#1677ff"><Check /></el-icon>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="theme-card"
|
||||
:class="{ 'is-active': form.sys_index_sideTheme === 'theme-light' }"
|
||||
@click="form.sys_index_sideTheme = 'theme-light'"
|
||||
>
|
||||
<div class="tc-preview tc-preview--light">
|
||||
<div class="tc-sidebar" />
|
||||
<div class="tc-body">
|
||||
<div class="tc-topbar" />
|
||||
<div class="tc-content" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="tc-label">
|
||||
<span>浅色主题</span>
|
||||
<el-icon v-if="form.sys_index_sideTheme === 'theme-light'" color="#1677ff"><Check /></el-icon>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</transition>
|
||||
|
||||
<!-- 操作栏 -->
|
||||
<div class="config-footer">
|
||||
<el-button @click="resetForm">重置</el-button>
|
||||
<el-button type="primary" :loading="saving" @click="submitForm">保存设置</el-button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
</BasicLayout>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getSetConfig, updateSetConfig } from '@/api/admin/sys-config'
|
||||
import { getToken } from '@/utils/auth'
|
||||
import { Setting, OfficeBuilding, Lock, Picture, Upload, Brush, Check } from '@element-plus/icons-vue'
|
||||
|
||||
export default {
|
||||
name: 'SysConfigSet',
|
||||
setup() {
|
||||
return { Setting, OfficeBuilding, Lock, Picture, Upload, Brush, Check }
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
activeSection: 0,
|
||||
saving: false,
|
||||
loading: false,
|
||||
configList: [],
|
||||
headers: { 'Authorization': 'Bearer ' + getToken() },
|
||||
form: {
|
||||
sys_app_name: undefined,
|
||||
sys_app_logo: null,
|
||||
sys_user_initPassword: undefined,
|
||||
sys_index_skinName: undefined,
|
||||
sys_index_sideTheme: undefined
|
||||
},
|
||||
rules: {
|
||||
sys_app_name: [{ required: true, message: '请输入系统名称', trigger: 'blur' }],
|
||||
sys_user_initPassword: [{ required: true, message: '请输入初始密码', trigger: 'blur' }]
|
||||
},
|
||||
sys_app_logoAction: process.env.VUE_APP_BASE_API + '/api/v1/public/uploadFile',
|
||||
sys_app_logofileList: [],
|
||||
sys_index_skinNameOptions: [{ label: '蓝色', value: 'skin-blue' }],
|
||||
sys_index_sideThemeOptions: [
|
||||
{ label: '深色主题', value: 'theme-dark' },
|
||||
{ label: '浅色主题', value: 'theme-light' }
|
||||
]
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
navItems() {
|
||||
return [
|
||||
{ label: '基础信息', sub: '名称、Logo、密码', icon: this.OfficeBuilding },
|
||||
{ label: '外观设置', sub: '皮肤与主题风格', icon: this.Brush }
|
||||
]
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getList()
|
||||
},
|
||||
methods: {
|
||||
getList() {
|
||||
this.loading = true
|
||||
getSetConfig().then(response => {
|
||||
this.form = response.data
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
submitForm() {
|
||||
this.$refs['form'].validate(valid => {
|
||||
if (!valid) return
|
||||
this.saving = true
|
||||
const list = Object.keys(this.form).map(key => ({ configKey: key, configValue: this.form[key] }))
|
||||
updateSetConfig(list).then(response => {
|
||||
if (response.code === 200) {
|
||||
this.msgSuccess(response.msg)
|
||||
this.getList()
|
||||
const { sys_app_name, sys_app_logo } = this.form
|
||||
this.$store.commit('system/SET_INFO', { sys_app_logo, sys_app_name })
|
||||
} else {
|
||||
this.msgError(response.msg)
|
||||
}
|
||||
}).finally(() => { this.saving = false })
|
||||
})
|
||||
},
|
||||
resetForm() {
|
||||
this.$refs['form'].resetFields()
|
||||
},
|
||||
sys_app_logoBeforeUpload(file) {
|
||||
const ok = file.size / 1024 / 1024 < 2
|
||||
if (!ok) this.$message.error('文件大小超过 2MB')
|
||||
return ok
|
||||
},
|
||||
uploadSuccess(response) {
|
||||
this.form.sys_app_logo = process.env.VUE_APP_BASE_API + response.data.full_path
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
// ── 页面容器 ──────────────────────────────────────────────
|
||||
.sys-config-set {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.config-wrapper {
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
// ══════════════════════════════
|
||||
// 左侧导航卡
|
||||
// ══════════════════════════════
|
||||
.config-sidebar {
|
||||
width: 188px;
|
||||
flex-shrink: 0;
|
||||
background: #fff;
|
||||
border-radius: 8px;
|
||||
border: 1px solid #f0f0f0;
|
||||
box-shadow: 0 1px 2px rgba(0,0,0,0.05);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.sidebar-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding: 14px 14px 12px;
|
||||
}
|
||||
|
||||
.sidebar-icon-box {
|
||||
width: 34px;
|
||||
height: 34px;
|
||||
border-radius: 8px;
|
||||
background: #e6f4ff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.sidebar-header__title {
|
||||
margin: 0 0 2px;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: #000000d9;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.sidebar-header__sub {
|
||||
margin: 0;
|
||||
font-size: 11px;
|
||||
color: #00000073;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.sidebar-divider {
|
||||
height: 1px;
|
||||
background: #f0f0f0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
// 导航项
|
||||
.nav-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding: 11px 14px;
|
||||
cursor: pointer;
|
||||
border-left: 2px solid transparent;
|
||||
transition: all 0.15s;
|
||||
|
||||
&:hover:not(.is-active) { background: #fafafa; }
|
||||
|
||||
&.is-active {
|
||||
background: #e6f4ff;
|
||||
border-left-color: #1677ff;
|
||||
|
||||
.nav-item__icon-wrap { color: #1677ff; background: rgba(22,119,255,0.1); }
|
||||
.nav-item__label { color: #1677ff; font-weight: 600; }
|
||||
}
|
||||
|
||||
&:not(:last-child) { border-bottom: 1px solid #f5f5f5; }
|
||||
}
|
||||
|
||||
.nav-item__icon-wrap {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
border-radius: 6px;
|
||||
background: #f5f5f5;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #00000073;
|
||||
flex-shrink: 0;
|
||||
transition: all 0.15s;
|
||||
}
|
||||
|
||||
.nav-item__text {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1px;
|
||||
}
|
||||
|
||||
.nav-item__label {
|
||||
font-size: 13px;
|
||||
color: #000000d9;
|
||||
font-weight: 500;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
.nav-item__sub {
|
||||
font-size: 11px;
|
||||
color: #00000045;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
// ══════════════════════════════
|
||||
// 右侧主内容
|
||||
// ══════════════════════════════
|
||||
.config-main {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
// 内容分区卡片
|
||||
.config-section {
|
||||
background: #fff;
|
||||
border-radius: 8px;
|
||||
border: 1px solid #f0f0f0;
|
||||
box-shadow: 0 1px 2px rgba(0,0,0,0.05);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
// 分区头部
|
||||
.section-head {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding: 14px 16px;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
background: #fafafa;
|
||||
}
|
||||
|
||||
.section-head__icon-wrap {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
border-radius: 6px;
|
||||
background: #e6f4ff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.section-head__title {
|
||||
margin: 0 0 2px;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: #000000d9;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.section-head__desc {
|
||||
margin: 0;
|
||||
font-size: 12px;
|
||||
color: #00000073;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
// 分区内容体
|
||||
.section-body {
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
// ── Logo 区域 ──────────────────────────────────────────
|
||||
.logo-zone {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16px;
|
||||
padding: 14px;
|
||||
background: #fafafa;
|
||||
border-radius: 6px;
|
||||
border: 1px dashed #d9d9d9;
|
||||
}
|
||||
|
||||
.logo-preview {
|
||||
width: 72px;
|
||||
height: 72px;
|
||||
border-radius: 8px;
|
||||
border: 1px solid #e8e8e8;
|
||||
background: #fff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.logo-img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.logo-empty {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
color: #c0c4cc;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.logo-meta { flex: 1; }
|
||||
|
||||
.logo-meta__name {
|
||||
margin: 0 0 3px;
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
color: #000000d9;
|
||||
}
|
||||
|
||||
.logo-meta__hint {
|
||||
margin: 0 0 10px;
|
||||
font-size: 12px;
|
||||
color: #00000073;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
// ── 主题选择 ─────────────────────────────────────────────
|
||||
.theme-label {
|
||||
margin: 12px 0 10px;
|
||||
font-size: 12px;
|
||||
color: #00000073;
|
||||
}
|
||||
|
||||
.theme-row {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.theme-card {
|
||||
width: 160px;
|
||||
border: 1px solid #e8e8e8;
|
||||
border-radius: 6px;
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s;
|
||||
|
||||
&:hover { border-color: #4096ff; box-shadow: 0 2px 8px rgba(22,119,255,0.12); }
|
||||
|
||||
&.is-active {
|
||||
border-color: #1677ff;
|
||||
box-shadow: 0 2px 8px rgba(22,119,255,0.2);
|
||||
}
|
||||
}
|
||||
|
||||
.tc-preview {
|
||||
display: flex;
|
||||
height: 80px;
|
||||
}
|
||||
|
||||
.tc-preview--dark {
|
||||
background: #1e2a3b;
|
||||
.tc-sidebar { background: #001529; }
|
||||
.tc-topbar { background: #162131; height: 16px; }
|
||||
.tc-content { flex: 1; background: #1e2a3b; }
|
||||
}
|
||||
|
||||
.tc-preview--light {
|
||||
background: #f5f5f5;
|
||||
.tc-sidebar { background: #fff; border-right: 1px solid #f0f0f0; }
|
||||
.tc-topbar { background: #fff; height: 16px; border-bottom: 1px solid #f0f0f0; }
|
||||
.tc-content { flex: 1; background: #f5f5f5; }
|
||||
}
|
||||
|
||||
.tc-sidebar {
|
||||
width: 36px;
|
||||
height: 100%;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.tc-body {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.tc-label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 6px 10px;
|
||||
font-size: 12px;
|
||||
color: #000000d9;
|
||||
background: #fff;
|
||||
border-top: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
// ── 底部操作栏 ────────────────────────────────────────────
|
||||
.config-footer {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 8px;
|
||||
padding: 12px 16px;
|
||||
background: #fff;
|
||||
border-radius: 8px;
|
||||
border: 1px solid #f0f0f0;
|
||||
box-shadow: 0 1px 2px rgba(0,0,0,0.05);
|
||||
}
|
||||
|
||||
// ── 过渡动画 ─────────────────────────────────────────────
|
||||
.fade-slide-enter-active,
|
||||
.fade-slide-leave-active {
|
||||
transition: opacity 0.15s, transform 0.15s;
|
||||
}
|
||||
|
||||
.fade-slide-enter-from { opacity: 0; transform: translateY(6px); }
|
||||
.fade-slide-leave-to { opacity: 0; transform: translateY(-6px); }
|
||||
</style>
|
||||
@@ -0,0 +1,377 @@
|
||||
<template>
|
||||
<BasicLayout>
|
||||
<template #wrapper>
|
||||
<el-card class="box-card">
|
||||
|
||||
<!-- 搜索区 -->
|
||||
<el-form ref="queryForm" :model="queryParams" :inline="true" class="search-form">
|
||||
<el-form-item label="部门名称" prop="deptName">
|
||||
<el-input
|
||||
v-model="queryParams.deptName"
|
||||
placeholder="请输入部门名称"
|
||||
clearable
|
||||
size="small"
|
||||
style="width: 200px"
|
||||
@keyup.enter="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="状态" prop="status">
|
||||
<el-select
|
||||
v-model="queryParams.status"
|
||||
placeholder="部门状态"
|
||||
clearable
|
||||
size="small"
|
||||
style="width: 140px"
|
||||
>
|
||||
<el-option
|
||||
v-for="dict in statusOptions"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" size="small" :icon="Search" @click="handleQuery">搜索</el-button>
|
||||
<el-button size="small" :icon="Refresh" @click="handleResetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<!-- 操作栏 -->
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
v-permisaction="['admin:sysDept:add']"
|
||||
type="primary"
|
||||
size="small"
|
||||
:icon="Plus"
|
||||
@click="handleAdd()"
|
||||
>新增</el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<!-- 数据表格 -->
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
:data="deptList"
|
||||
row-key="deptId"
|
||||
default-expand-all
|
||||
border
|
||||
stripe
|
||||
highlight-current-row
|
||||
:tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
|
||||
>
|
||||
<el-table-column prop="deptName" label="部门名称" min-width="160" />
|
||||
<el-table-column prop="sort" label="排序" width="80" align="center" />
|
||||
<el-table-column prop="status" label="状态" width="90" align="center">
|
||||
<template #default="scope">
|
||||
<el-tag
|
||||
:type="scope.row.status === 1 ? 'danger' : 'success'"
|
||||
size="small"
|
||||
disable-transitions
|
||||
>{{ statusFormat(scope.row) }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="创建时间" align="center" prop="createdAt" width="180">
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.createdAt) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" width="200" class-name="small-padding fixed-width">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
v-permisaction="['admin:sysDept:edit']"
|
||||
size="small"
|
||||
type="primary"
|
||||
link
|
||||
:icon="Edit"
|
||||
@click="handleUpdate(scope.row)"
|
||||
>修改</el-button>
|
||||
<el-divider direction="vertical" />
|
||||
<el-button
|
||||
v-permisaction="['admin:sysDept:add']"
|
||||
size="small"
|
||||
type="primary"
|
||||
link
|
||||
:icon="Plus"
|
||||
@click="handleAdd(scope.row)"
|
||||
>新增</el-button>
|
||||
<template v-if="scope.row.p_id != 0">
|
||||
<el-divider direction="vertical" />
|
||||
<el-button
|
||||
v-permisaction="['admin:sysDept:remove']"
|
||||
size="small"
|
||||
type="danger"
|
||||
link
|
||||
:icon="Delete"
|
||||
@click="handleDelete(scope.row)"
|
||||
>删除</el-button>
|
||||
</template>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<!-- 添加或修改部门对话框 -->
|
||||
<el-dialog v-model="open" :title="title" width="600px" :close-on-click-modal="false">
|
||||
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
|
||||
<el-row>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="上级部门" prop="parentId">
|
||||
<treeselect
|
||||
v-model="form.parentId"
|
||||
:options="deptOptions"
|
||||
:normalizer="normalizer"
|
||||
:show-count="true"
|
||||
placeholder="选择上级部门"
|
||||
:is-disabled="isEdit"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="部门名称" prop="deptName">
|
||||
<el-input v-model="form.deptName" placeholder="请输入部门名称" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="显示排序" prop="orderNum">
|
||||
<el-input-number v-model="form.sort" controls-position="right" :min="0" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="负责人" prop="leader">
|
||||
<el-input v-model="form.leader" placeholder="请输入负责人" maxlength="20" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="联系电话" prop="phone">
|
||||
<el-input v-model="form.phone" placeholder="请输入联系电话" maxlength="11" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="邮箱" prop="email">
|
||||
<el-input v-model="form.email" placeholder="请输入邮箱" maxlength="50" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="部门状态">
|
||||
<el-radio-group v-model="form.status">
|
||||
<el-radio
|
||||
v-for="dict in statusOptions"
|
||||
:key="dict.value"
|
||||
:label="dict.value"
|
||||
>{{ dict.label }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
</el-card>
|
||||
</template>
|
||||
</BasicLayout>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getDeptList, getDept, delDept, addDept, updateDept } from '@/api/admin/sys-dept'
|
||||
import Treeselect from 'vue3-treeselect'
|
||||
import 'vue3-treeselect/dist/vue3-treeselect.css'
|
||||
import { Search, Refresh, Plus, Edit, Delete } from '@element-plus/icons-vue'
|
||||
|
||||
export default {
|
||||
name: 'SysDeptManage',
|
||||
components: { Treeselect },
|
||||
setup() {
|
||||
return { Search, Refresh, Plus, Edit, Delete }
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: true,
|
||||
deptList: [],
|
||||
deptOptions: [],
|
||||
title: '',
|
||||
isEdit: false,
|
||||
open: false,
|
||||
statusOptions: [],
|
||||
queryParams: {
|
||||
deptName: undefined,
|
||||
status: undefined
|
||||
},
|
||||
form: {},
|
||||
rules: {
|
||||
parentId: [
|
||||
{ required: true, message: '上级部门不能为空', trigger: 'blur' }
|
||||
],
|
||||
deptName: [
|
||||
{ required: true, message: '部门名称不能为空', trigger: 'blur' }
|
||||
],
|
||||
sort: [
|
||||
{ required: true, message: '菜单顺序不能为空', trigger: 'blur' }
|
||||
],
|
||||
leader: [
|
||||
{ required: true, message: '负责人不能为空', trigger: 'blur' }
|
||||
],
|
||||
email: [
|
||||
{
|
||||
type: 'email',
|
||||
message: '请输入正确的邮箱地址',
|
||||
trigger: ['blur', 'change']
|
||||
}
|
||||
],
|
||||
phone: [
|
||||
{
|
||||
pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/,
|
||||
message: '请输入正确的手机号码',
|
||||
trigger: 'blur'
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getList()
|
||||
this.getDicts('sys_normal_disable').then(response => {
|
||||
this.statusOptions = response.data
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
getList() {
|
||||
this.loading = true
|
||||
getDeptList(this.queryParams).then(response => {
|
||||
this.deptList = response.data
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
normalizer(node) {
|
||||
if (node.children && !node.children.length) {
|
||||
delete node.children
|
||||
}
|
||||
return {
|
||||
id: node.deptId,
|
||||
label: node.deptName,
|
||||
children: node.children
|
||||
}
|
||||
},
|
||||
getTreeselect(e) {
|
||||
getDeptList().then(response => {
|
||||
this.deptOptions = []
|
||||
if (e === 'update') {
|
||||
const dept = { deptId: 0, deptName: '主类目', children: [], isDisabled: true }
|
||||
dept.children = response.data
|
||||
this.deptOptions.push(dept)
|
||||
} else {
|
||||
const dept = { deptId: 0, deptName: '主类目', children: [] }
|
||||
dept.children = response.data
|
||||
this.deptOptions.push(dept)
|
||||
}
|
||||
})
|
||||
},
|
||||
statusFormat(row) {
|
||||
return this.selectDictLabel(this.statusOptions, parseInt(row.status))
|
||||
},
|
||||
cancel() {
|
||||
this.open = false
|
||||
this.reset()
|
||||
},
|
||||
reset() {
|
||||
this.form = {
|
||||
deptId: undefined,
|
||||
parentId: undefined,
|
||||
deptName: undefined,
|
||||
sort: 10,
|
||||
leader: undefined,
|
||||
phone: undefined,
|
||||
email: undefined,
|
||||
status: '2'
|
||||
}
|
||||
},
|
||||
handleQuery() {
|
||||
this.getList()
|
||||
},
|
||||
handleResetQuery() {
|
||||
this.queryParams = { deptName: undefined, status: undefined }
|
||||
this.getList()
|
||||
},
|
||||
handleAdd(row) {
|
||||
this.reset()
|
||||
this.getTreeselect('add')
|
||||
if (row !== undefined) {
|
||||
this.form.parentId = row.deptId
|
||||
}
|
||||
this.open = true
|
||||
this.title = '添加部门'
|
||||
this.isEdit = false
|
||||
},
|
||||
handleUpdate(row) {
|
||||
this.reset()
|
||||
this.getTreeselect('update')
|
||||
getDept(row.deptId).then(response => {
|
||||
this.form = response.data
|
||||
this.form.status = String(this.form.status)
|
||||
this.form.sort = String(this.form.sort)
|
||||
this.open = true
|
||||
this.title = '修改部门'
|
||||
this.isEdit = true
|
||||
})
|
||||
},
|
||||
submitForm: function() {
|
||||
this.$refs['form'].validate(valid => {
|
||||
if (valid) {
|
||||
this.form.status = parseInt(this.form.status)
|
||||
this.form.sort = parseInt(this.form.sort)
|
||||
if (this.form.deptId !== undefined) {
|
||||
updateDept(this.form, this.form.deptId).then(response => {
|
||||
if (response.code === 200) {
|
||||
this.msgSuccess(response.msg)
|
||||
this.open = false
|
||||
this.getList()
|
||||
} else {
|
||||
this.msgError(response.msg)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
addDept(this.form).then(response => {
|
||||
if (response.code === 200) {
|
||||
this.msgSuccess(response.msg)
|
||||
this.open = false
|
||||
this.getList()
|
||||
} else {
|
||||
this.msgError(response.msg)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
handleDelete(row) {
|
||||
const Ids = (row.deptId && [row.deptId]) || this.ids
|
||||
this.$confirm(
|
||||
'是否确认删除名称为"' + row.deptName + '"的数据项?',
|
||||
'警告',
|
||||
{
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}
|
||||
)
|
||||
.then(function() {
|
||||
return delDept({ 'ids': Ids })
|
||||
}).then((response) => {
|
||||
if (response.code === 200) {
|
||||
this.msgSuccess(response.msg)
|
||||
this.open = false
|
||||
this.getList()
|
||||
} else {
|
||||
this.msgError(response.msg)
|
||||
}
|
||||
}).catch(function() {})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,287 @@
|
||||
|
||||
<template>
|
||||
<BasicLayout>
|
||||
<template #wrapper>
|
||||
<el-card class="box-card">
|
||||
<el-form ref="queryForm" :model="queryParams" :inline="true" class="search-form">
|
||||
<el-form-item label="用户名" prop="username">
|
||||
<el-input
|
||||
v-model="queryParams.username"
|
||||
placeholder="请输入用户名"
|
||||
clearable
|
||||
size="small"
|
||||
@keyup.enter="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="状态" prop="status">
|
||||
<el-select
|
||||
v-model="queryParams.status"
|
||||
placeholder="系统登录日志状态"
|
||||
clearable
|
||||
size="small"
|
||||
>
|
||||
<el-option
|
||||
v-for="dict in statusOptions"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="ip地址" prop="ipaddr">
|
||||
<el-input
|
||||
v-model="queryParams.ipaddr"
|
||||
placeholder="请输入ip地址"
|
||||
clearable
|
||||
size="small"
|
||||
@keyup.enter="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
<el-button type="primary" size="small" :icon="Search" @click="handleQuery">搜索</el-button>
|
||||
<el-button size="small" :icon="Refresh" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<div class="toolbar mb8">
|
||||
<el-button v-permisaction="['admin:sysLoginLog:remove']" type="danger" size="small" :icon="Delete" :disabled="multiple" @click="handleDelete">删除</el-button>
|
||||
</div>
|
||||
|
||||
<el-table v-loading="loading" :data="sysloginlogList" border stripe @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column
|
||||
label="用户名"
|
||||
align="center"
|
||||
prop="username"
|
||||
:show-overflow-tooltip="true"
|
||||
/>
|
||||
<el-table-column
|
||||
label="类型"
|
||||
align="center"
|
||||
prop="msg"
|
||||
:show-overflow-tooltip="true"
|
||||
/>
|
||||
<el-table-column
|
||||
label="状态"
|
||||
align="center"
|
||||
prop="status"
|
||||
width="100"
|
||||
>
|
||||
<template #default="scope">
|
||||
<el-tag :type="scope.row.status === '2' || scope.row.status === 2 ? 'success' : 'danger'" size="small" disable-transitions>
|
||||
{{ statusFormat(scope.row) }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
label="ip地址"
|
||||
align="center"
|
||||
prop="ipaddr"
|
||||
>
|
||||
<template #default="scope">
|
||||
<el-popover trigger="hover" placement="top">
|
||||
<p>IP: {{ scope.row.ipaddr }}</p>
|
||||
<p>归属地: {{ scope.row.loginLocation }}</p>
|
||||
<p>浏览器: {{ scope.row.browser }}</p>
|
||||
<p>系统: {{ scope.row.os }}</p>
|
||||
<p>固件: {{ scope.row.platform }}</p>
|
||||
<template #reference><div class="name-wrapper">
|
||||
{{ scope.row.ipaddr }}
|
||||
</div></template>
|
||||
</el-popover>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
label="登录时间"
|
||||
align="center"
|
||||
prop="loginTime"
|
||||
width="180"
|
||||
>
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.loginTime) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||
<template #default="scope">
|
||||
<el-button v-permisaction="['admin:sysLoginLog:remove']" type="danger" link size="small" :icon="Delete" @click="handleDelete(scope.row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<pagination
|
||||
v-show="total>0"
|
||||
v-model:current-page="queryParams.pageIndex"
|
||||
v-model:page-size="queryParams.pageSize"
|
||||
:total="total"
|
||||
@pagination="getList"
|
||||
/>
|
||||
</el-card>
|
||||
</template>
|
||||
</BasicLayout>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { delSysLoginlog, getSysLoginlog, listSysLoginlog } from '@/api/admin/sys-login-log'
|
||||
import { Search, Refresh, Delete } from '@element-plus/icons-vue'
|
||||
|
||||
export default {
|
||||
name: 'SysLoginLogManage',
|
||||
components: {
|
||||
},
|
||||
setup() {
|
||||
return { Search, Refresh, Delete }
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 选中数组
|
||||
ids: [],
|
||||
// 非单个禁用
|
||||
single: true,
|
||||
// 非多个禁用
|
||||
multiple: true,
|
||||
// 总条数
|
||||
total: 0,
|
||||
// 弹出层标题
|
||||
title: '',
|
||||
// 是否显示弹出层
|
||||
open: false,
|
||||
isEdit: false,
|
||||
fileOpen: false,
|
||||
fileIndex: undefined,
|
||||
// 类型数据字典
|
||||
typeOptions: [],
|
||||
sysloginlogList: [],
|
||||
statusOptions: [],
|
||||
// 关系表类型
|
||||
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageIndex: 1,
|
||||
pageSize: 10,
|
||||
username: undefined,
|
||||
status: undefined,
|
||||
ipaddr: undefined,
|
||||
loginLocation: undefined,
|
||||
createdAtOrder: 'desc'
|
||||
},
|
||||
// 表单参数
|
||||
form: {
|
||||
},
|
||||
// 表单校验
|
||||
rules: {
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getList()
|
||||
this.getDicts('sys_common_status').then(response => {
|
||||
this.statusOptions = response.data
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
/** 查询参数列表 */
|
||||
getList() {
|
||||
this.loading = true
|
||||
listSysLoginlog(this.addDateRange(this.queryParams, this.dateRange)).then(response => {
|
||||
this.sysloginlogList = response.data.list
|
||||
this.total = response.data.count
|
||||
this.loading = false
|
||||
}
|
||||
)
|
||||
},
|
||||
// 取消按钮
|
||||
cancel() {
|
||||
this.open = false
|
||||
this.reset()
|
||||
},
|
||||
// 表单重置
|
||||
reset() {
|
||||
this.form = {
|
||||
ID: undefined,
|
||||
username: undefined,
|
||||
status: undefined,
|
||||
ipaddr: undefined,
|
||||
loginLocation: undefined,
|
||||
browser: undefined,
|
||||
os: undefined,
|
||||
platform: undefined,
|
||||
loginTime: undefined,
|
||||
remark: undefined,
|
||||
msg: undefined
|
||||
}
|
||||
this.resetForm('form')
|
||||
},
|
||||
getImgList: function() {
|
||||
this.form[this.fileIndex] = this.$refs['fileChoose'].resultList[0].fullUrl
|
||||
},
|
||||
fileClose: function() {
|
||||
this.fileOpen = false
|
||||
},
|
||||
statusFormat(row) {
|
||||
return this.selectDictLabel(this.statusOptions, row.status)
|
||||
},
|
||||
// 关系
|
||||
// 文件
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
this.queryParams.pageIndex = 1
|
||||
this.getList()
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.dateRange = []
|
||||
this.resetForm('queryForm')
|
||||
this.handleQuery()
|
||||
},
|
||||
/** 新增按钮操作 */
|
||||
handleAdd() {
|
||||
this.reset()
|
||||
this.open = true
|
||||
this.title = '添加系统登录日志'
|
||||
this.isEdit = false
|
||||
},
|
||||
// 多选框选中数据
|
||||
handleSelectionChange(selection) {
|
||||
this.ids = selection.map(item => item.id)
|
||||
this.single = selection.length !== 1
|
||||
this.multiple = !selection.length
|
||||
},
|
||||
/** 修改按钮操作 */
|
||||
handleUpdate(row) {
|
||||
this.reset()
|
||||
const ID =
|
||||
row.id || this.ids
|
||||
getSysLoginlog(ID).then(response => {
|
||||
this.form = response.data
|
||||
this.open = true
|
||||
this.title = '修改系统登录日志'
|
||||
this.isEdit = true
|
||||
})
|
||||
},
|
||||
/** 删除按钮操作 */
|
||||
handleDelete(row) {
|
||||
var Ids = (row.id && [row.id]) || this.ids
|
||||
|
||||
this.$confirm('是否确认删除编号为"' + Ids + '"的数据项?', '警告', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(function() {
|
||||
return delSysLoginlog({ 'ids': Ids })
|
||||
}).then((response) => {
|
||||
if (response.code === 200) {
|
||||
this.msgSuccess(response.msg)
|
||||
this.open = false
|
||||
this.getList()
|
||||
} else {
|
||||
this.msgError(response.msg)
|
||||
}
|
||||
}).catch(function() {})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,634 @@
|
||||
<template>
|
||||
<BasicLayout>
|
||||
<template #wrapper>
|
||||
<el-card class="box-card">
|
||||
<el-form :inline="true" class="search-form">
|
||||
<el-form-item label="菜单名称">
|
||||
<el-input
|
||||
v-model="queryParams.title"
|
||||
placeholder="请输入菜单名称"
|
||||
clearable
|
||||
size="small"
|
||||
@keyup.enter="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="状态">
|
||||
<el-select v-model="queryParams.visible" placeholder="菜单状态" clearable size="small">
|
||||
<el-option
|
||||
v-for="dict in visibleOptions"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" size="small" :icon="Search" @click="handleQuery">搜索</el-button>
|
||||
<el-button v-permisaction="['admin:sysMenu:add']" type="primary" size="small" :icon="Plus" @click="handleAdd">新增</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
:data="menuList"
|
||||
border
|
||||
stripe
|
||||
row-key="menuId"
|
||||
:tree-props="{children: 'children', hasChildren: 'hasChildren'}"
|
||||
>
|
||||
<el-table-column prop="title" label="菜单名称" :show-overflow-tooltip="true" width="180px" />
|
||||
<el-table-column prop="icon" label="图标" align="center" width="100px">
|
||||
<template #default="scope">
|
||||
<svg-icon :icon-class="scope.row.icon" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="sort" label="排序" width="60px" />
|
||||
<el-table-column prop="permission" label="权限标识" :show-overflow-tooltip="true">
|
||||
<template #default="scope">
|
||||
<el-popover v-if="scope.row.sysApi.length>0" trigger="hover" placement="top">
|
||||
<el-table
|
||||
:data="scope.row.sysApi"
|
||||
border
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-table-column
|
||||
prop="title"
|
||||
label="title"
|
||||
width="260px"
|
||||
>
|
||||
<template #default="scope">
|
||||
<span v-if="scope.row.type=='SYS' && scope.row.title!=''"><el-tag type="success">{{ '['+scope.row.type +'] '+ scope.row.title }}</el-tag></span>
|
||||
<span v-if="scope.row.type!='SYS' && scope.row.title!=''"><el-tag type="">{{ '['+scope.row.type +'] '+scope.row.title }}</el-tag></span>
|
||||
<span v-if="scope.row.title==''"><el-tag type="danger">暂无</el-tag></span>
|
||||
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="path"
|
||||
label="path"
|
||||
width="270px"
|
||||
>
|
||||
<template #default="scope">
|
||||
<el-tag v-if="scope.row.action=='GET'">{{ scope.row.action }}</el-tag>
|
||||
<el-tag v-if="scope.row.action=='POST'" type="success">{{ scope.row.action }}</el-tag>
|
||||
<el-tag v-if="scope.row.action=='PUT'" type="warning">{{ scope.row.action }}</el-tag>
|
||||
<el-tag v-if="scope.row.action=='DELETE'" type="danger">{{ scope.row.action }}</el-tag>
|
||||
{{ scope.row.path }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
</el-table>
|
||||
<template #reference><div class="name-wrapper">
|
||||
<span v-if="scope.row.permission==''">-</span>
|
||||
<span v-else>{{ scope.row.permission }}</span>
|
||||
</div></template>
|
||||
</el-popover>
|
||||
<span v-else>
|
||||
<span v-if="scope.row.permission==''">-</span>
|
||||
<span v-else>{{ scope.row.permission }}</span>
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="path" label="组件路径" :show-overflow-tooltip="true">
|
||||
<template #default="scope">
|
||||
<span v-if="scope.row.menuType=='A'">{{ scope.row.path }}</span>
|
||||
<span v-else>{{ scope.row.component }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="visible" label="可见" :formatter="visibleFormat" width="80">
|
||||
<template #default="scope">
|
||||
<el-tag
|
||||
:type="scope.row.visible === '1' ? 'danger' : 'success'"
|
||||
disable-transitions
|
||||
>{{ visibleFormat(scope.row) }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="创建时间" align="center" prop="createdAt" width="180">
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.createdAt) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="220">
|
||||
<template #default="scope">
|
||||
<el-button v-permisaction="['admin:sysMenu:edit']" type="primary" link size="small" :icon="Edit" @click="handleUpdate(scope.row)">修改</el-button>
|
||||
<el-divider direction="vertical" />
|
||||
<el-button v-permisaction="['admin:sysMenu:add']" type="primary" link size="small" :icon="Plus" @click="handleAdd(scope.row)">新增</el-button>
|
||||
<el-divider direction="vertical" />
|
||||
<el-button v-permisaction="['admin:sysMenu:remove']" type="danger" link size="small" :icon="Delete" @click="handleDelete(scope.row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<!-- 添加或修改菜单对话框 -->
|
||||
<el-drawer
|
||||
ref="drawer"
|
||||
v-model="open"
|
||||
:title="title"
|
||||
:before-close="cancel"
|
||||
direction="rtl"
|
||||
custom-class="demo-drawer"
|
||||
size="830px"
|
||||
>
|
||||
<div class="demo-drawer__content">
|
||||
<el-form ref="form" :model="form" :rules="rules" label-position="top" label-width="106px">
|
||||
<el-row>
|
||||
<el-col :span="24">
|
||||
<el-form-item prop="parentId">
|
||||
<template #label>
|
||||
<span>
|
||||
上级菜单
|
||||
<el-tooltip content="指当前菜单停靠的菜单归属" placement="top">
|
||||
<i class="ri-question-line" />
|
||||
</el-tooltip>
|
||||
</span>
|
||||
</template>
|
||||
<treeselect
|
||||
v-model="form.parentId"
|
||||
:options="menuOptions"
|
||||
:normalizer="normalizer"
|
||||
:show-count="true"
|
||||
placeholder="选择上级菜单"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item prop="title">
|
||||
<template #label>
|
||||
<span>
|
||||
菜单标题
|
||||
<el-tooltip content="菜单位置显示的说明信息" placement="top">
|
||||
<i class="ri-question-line" />
|
||||
</el-tooltip>
|
||||
</span>
|
||||
</template>
|
||||
<el-input v-model="form.title" placeholder="请输入菜单标题" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item prop="sort">
|
||||
<template #label>
|
||||
<span>
|
||||
显示排序
|
||||
<el-tooltip content="根据序号升序排列" placement="top">
|
||||
<i class="ri-question-line" />
|
||||
</el-tooltip>
|
||||
</span>
|
||||
</template>
|
||||
<el-input-number v-model="form.sort" controls-position="right" :min="0" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="24">
|
||||
<el-form-item prop="menuType">
|
||||
<template #label>
|
||||
<span>
|
||||
菜单类型
|
||||
<el-tooltip content="包含目录:以及菜单或者菜单组,菜单:具体对应某一个页面,按钮:功能才做按钮;" placement="top">
|
||||
<i class="ri-question-line" />
|
||||
</el-tooltip>
|
||||
</span>
|
||||
</template>
|
||||
<el-radio-group v-model="form.menuType">
|
||||
<el-radio label="M">目录</el-radio>
|
||||
<el-radio label="C">菜单</el-radio>
|
||||
<el-radio label="F">按钮</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="菜单图标">
|
||||
<el-popover
|
||||
placement="bottom-start"
|
||||
width="460"
|
||||
trigger="click"
|
||||
@show="$refs['iconSelect'].reset()"
|
||||
>
|
||||
<IconSelect ref="iconSelect" @selected="selected" />
|
||||
<template #reference>
|
||||
<el-input v-model="form.icon" placeholder="点击选择图标" readonly>
|
||||
<template #prefix>
|
||||
<svg-icon
|
||||
v-if="form.icon"
|
||||
:icon-class="form.icon"
|
||||
class="el-input__icon"
|
||||
style="height: 32px;width: 16px;"
|
||||
/>
|
||||
<i v-else class="ri-search-line el-input__icon" />
|
||||
</template>
|
||||
</el-input>
|
||||
</template>
|
||||
</el-popover>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item v-if="form.menuType == 'M' || form.menuType == 'C'" prop="menuName">
|
||||
<template #label>
|
||||
<span>
|
||||
路由名称
|
||||
<el-tooltip content="需要和页面name保持一致,对应页面即可选择缓存" placement="top">
|
||||
<i class="ri-question-line" />
|
||||
</el-tooltip>
|
||||
</span>
|
||||
</template>
|
||||
<el-input v-model="form.menuName" placeholder="请输入路由名称" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col v-if="form.menuType == 'M' || form.menuType == 'C'" :span="12">
|
||||
<el-form-item prop="component">
|
||||
<template #label>
|
||||
<span>
|
||||
组件路径
|
||||
<el-tooltip content="菜单对应的具体vue页面文件路径views的下级路径/admin/sys-api/index;目录类型:填写Layout,如何有二级目录请参照日志目录填写;" placement="top">
|
||||
<i class="ri-question-line" />
|
||||
</el-tooltip>
|
||||
</span>
|
||||
</template>
|
||||
<el-input v-model="form.component" placeholder="请输入组件路径" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="12">
|
||||
<el-form-item v-if="form.menuType == 'M' || form.menuType == 'C'">
|
||||
<template #label>
|
||||
<span>
|
||||
是否外链
|
||||
<el-tooltip content="可以通过iframe打开指定地址" placement="top">
|
||||
<i class="ri-question-line" />
|
||||
</el-tooltip>
|
||||
</span>
|
||||
</template>
|
||||
<el-radio-group v-model="form.isFrame">
|
||||
<el-radio label="0">是</el-radio>
|
||||
<el-radio label="1">否</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="12">
|
||||
<el-form-item v-if="form.menuType != 'F'" prop="path">
|
||||
<template #label>
|
||||
<span>
|
||||
路由地址
|
||||
<el-tooltip content="访问此页面自定义的url地址,建议/开头书写,例如 /app-name/menu-name" placement="top">
|
||||
<i class="ri-question-line" />
|
||||
</el-tooltip>
|
||||
</span>
|
||||
</template>
|
||||
<el-input v-model="form.path" placeholder="请输入路由地址" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="12">
|
||||
<el-form-item v-if="form.menuType == 'F' || form.menuType == 'C'">
|
||||
<template #label>
|
||||
<span>
|
||||
权限标识
|
||||
<el-tooltip content="前端权限控制按钮是否显示" placement="top">
|
||||
<i class="ri-question-line" />
|
||||
</el-tooltip>
|
||||
</span>
|
||||
</template>
|
||||
<el-input v-model="form.permission" placeholder="请权限标识" maxlength="50" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item v-if="form.menuType != 'F'">
|
||||
<template #label>
|
||||
<span>
|
||||
菜单状态
|
||||
<el-tooltip content="需要显示在菜单列表的菜单设置为显示,否则设置为隐藏" placement="top">
|
||||
<i class="ri-question-line" />
|
||||
</el-tooltip>
|
||||
</span>
|
||||
</template>
|
||||
<el-radio-group v-model="form.visible">
|
||||
<el-radio
|
||||
v-for="dict in visibleOptions"
|
||||
:key="dict.value"
|
||||
:label="dict.value"
|
||||
>{{ dict.label }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item v-if="form.menuType == 'F' || form.menuType == 'C'">
|
||||
<template #label>
|
||||
<span>
|
||||
api权限
|
||||
<el-tooltip content="配置在这个才做上需要使用到的接口,否则在设置用户角色时,接口将无权访问。" placement="top">
|
||||
<i class="ri-question-line" />
|
||||
</el-tooltip>
|
||||
</span>
|
||||
</template>
|
||||
<el-transfer
|
||||
v-model="form.apis"
|
||||
style="text-align: left; display: inline-block"
|
||||
filterable
|
||||
:props="{
|
||||
key: 'id',
|
||||
label: 'title'
|
||||
}"
|
||||
:titles="['未授权', '已授权']"
|
||||
:button-texts="['收回', '授权 ']"
|
||||
:format="{
|
||||
noChecked: '${total}',
|
||||
hasChecked: '${checked}/${total}'
|
||||
}"
|
||||
class="panel"
|
||||
:data="sysapiList"
|
||||
@change="handleChange"
|
||||
>
|
||||
<template #default="{ option }">
|
||||
<span>{{ option.title }}</span>
|
||||
</template>
|
||||
</el-transfer>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<div class="demo-drawer__footer">
|
||||
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</el-drawer>
|
||||
</el-card>
|
||||
</template>
|
||||
</BasicLayout>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { listMenu, getMenu, delMenu, addMenu, updateMenu } from '@/api/admin/sys-menu'
|
||||
import { listSysApi } from '@/api/admin/sys-api'
|
||||
|
||||
import Treeselect from 'vue3-treeselect'
|
||||
import 'vue3-treeselect/dist/vue3-treeselect.css'
|
||||
import IconSelect from '@/components/IconSelect'
|
||||
import { Search, Plus, Edit, Delete } from '@element-plus/icons-vue'
|
||||
|
||||
export default {
|
||||
name: 'SysMenuManage',
|
||||
components: { Treeselect, IconSelect },
|
||||
setup() {
|
||||
return { Search, Plus, Edit, Delete }
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 菜单表格树数据
|
||||
menuList: [],
|
||||
sysapiList: [],
|
||||
// 菜单树选项
|
||||
menuOptions: [],
|
||||
// 弹出层标题
|
||||
title: '',
|
||||
// 是否显示弹出层
|
||||
open: false,
|
||||
// 菜单状态数据字典
|
||||
visibleOptions: [],
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
title: undefined,
|
||||
visible: undefined
|
||||
},
|
||||
// 表单参数
|
||||
form: {
|
||||
apis: [],
|
||||
sysApi: []
|
||||
},
|
||||
// 表单校验
|
||||
rules: {
|
||||
title: [{ required: true, message: '菜单标题不能为空', trigger: 'blur' }],
|
||||
sort: [{ required: true, message: '菜单顺序不能为空', trigger: 'blur' }]
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getList()
|
||||
|
||||
this.getApiList()
|
||||
this.getDicts('sys_show_hide').then(response => {
|
||||
this.visibleOptions = response.data
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
handleChange(value, direction, movedKeys) {
|
||||
console.log(value, direction, movedKeys)
|
||||
const list = this.form.sysApi
|
||||
this.form.apis = value
|
||||
if (direction === 'right') {
|
||||
for (let x = 0; x < movedKeys.length; x++) {
|
||||
for (let index = 0; index < this.sysapiList.length; index++) {
|
||||
const element = this.sysapiList[index]
|
||||
if (element.id === movedKeys[x]) {
|
||||
list.push(element)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
this.form.sysApi = list
|
||||
} else if (direction === 'left') {
|
||||
const l = []
|
||||
for (let index = 0; index < movedKeys.length; index++) {
|
||||
const element = movedKeys[index]
|
||||
for (let x = 0; x < list.length; x++) {
|
||||
const e = list[x]
|
||||
if (element !== e.id) {
|
||||
l.push()
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
this.form.sysApi = l
|
||||
}
|
||||
// this.setApis(this.form.SysApi)
|
||||
console.log(this.form.sysApi)
|
||||
},
|
||||
getApiList() {
|
||||
this.loading = true
|
||||
listSysApi({ 'pageSize': 10000, 'type': 'BUS' }).then(response => {
|
||||
this.sysapiList = response.data.list
|
||||
this.loading = false
|
||||
}
|
||||
)
|
||||
},
|
||||
handleClose(done) {
|
||||
// if (this.loading) {
|
||||
// return
|
||||
// }
|
||||
// this.$confirm('需要提交表单吗?')
|
||||
// .then(_ => {
|
||||
// this.loading = true
|
||||
// this.timer = setTimeout(() => {
|
||||
// done()
|
||||
// // 动画关闭需要一定的时间
|
||||
// setTimeout(() => {
|
||||
// this.loading = false
|
||||
// }, 400)
|
||||
// }, 1000)
|
||||
// })
|
||||
// .catch(_ => {})
|
||||
},
|
||||
// 选择图标
|
||||
selected(name) {
|
||||
this.form.icon = name
|
||||
},
|
||||
/** 查询菜单列表 */
|
||||
getList() {
|
||||
this.loading = true
|
||||
listMenu(this.queryParams).then(response => {
|
||||
this.menuList = response.data
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
/** 转换菜单数据结构 */
|
||||
normalizer(node) {
|
||||
if (node.children && !node.children.length) {
|
||||
delete node.children
|
||||
}
|
||||
return {
|
||||
id: node.menuId,
|
||||
label: node.title,
|
||||
children: node.children
|
||||
}
|
||||
},
|
||||
/** 查询菜单下拉树结构 */
|
||||
getTreeselect() {
|
||||
listMenu().then(response => {
|
||||
this.menuOptions = []
|
||||
const menu = { menuId: 0, title: '主类目', children: [] }
|
||||
menu.children = response.data
|
||||
this.menuOptions.push(menu)
|
||||
})
|
||||
},
|
||||
// 菜单显示状态字典翻译
|
||||
visibleFormat(row) {
|
||||
if (row.menuType === 'F') {
|
||||
return '-- --'
|
||||
}
|
||||
return this.selectDictLabel(this.visibleOptions, row.visible)
|
||||
},
|
||||
// 取消按钮
|
||||
cancel() {
|
||||
this.open = false
|
||||
this.reset()
|
||||
},
|
||||
// 表单重置
|
||||
reset() {
|
||||
this.form = {
|
||||
menuId: undefined,
|
||||
parentId: 0,
|
||||
menuName: undefined,
|
||||
icon: undefined,
|
||||
menuType: 'M',
|
||||
apis: [],
|
||||
sort: 0,
|
||||
action: this.form.menuType === 'A' ? this.form.action : '',
|
||||
isFrame: '1',
|
||||
visible: '0'
|
||||
}
|
||||
this.resetForm('form')
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
this.getList()
|
||||
},
|
||||
/** 新增按钮操作 */
|
||||
handleAdd(row) {
|
||||
this.reset()
|
||||
this.getTreeselect()
|
||||
if (row != null) {
|
||||
this.form.parentId = row.menuId
|
||||
}
|
||||
this.open = true
|
||||
this.title = '添加菜单'
|
||||
},
|
||||
/** 修改按钮操作 */
|
||||
handleUpdate(row) {
|
||||
this.reset()
|
||||
this.getTreeselect()
|
||||
getMenu(row.menuId).then(response => {
|
||||
this.form = response.data
|
||||
this.open = true
|
||||
this.title = '修改菜单'
|
||||
})
|
||||
},
|
||||
setApis(apiArray) {
|
||||
var l = []
|
||||
for (var index = 0; index < apiArray.length; index++) {
|
||||
const element = apiArray[index]
|
||||
l.push(element.id)
|
||||
}
|
||||
this.form.apis = l
|
||||
},
|
||||
/** 提交按钮 */
|
||||
submitForm: function() {
|
||||
this.$refs['form'].validate(valid => {
|
||||
if (valid) {
|
||||
if (this.form.menuId !== undefined) {
|
||||
updateMenu(this.form, this.form.menuId).then(response => {
|
||||
if (response.code === 200) {
|
||||
this.msgSuccess(response.msg)
|
||||
this.open = false
|
||||
this.getList()
|
||||
} else {
|
||||
this.msgError(response.msg)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
addMenu(this.form).then(response => {
|
||||
if (response.code === 200) {
|
||||
this.msgSuccess(response.msg)
|
||||
this.open = false
|
||||
this.getList()
|
||||
} else {
|
||||
this.msgError(response.msg)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
/** 删除按钮操作 */
|
||||
handleDelete(row) {
|
||||
this.$confirm('是否确认删除名称为"' + row.title + '"的数据项?', '警告', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(function() {
|
||||
var Ids = (row.menuId && [row.menuId]) || this.ids
|
||||
return delMenu({ 'ids': Ids })
|
||||
}).then((response) => {
|
||||
if (response.code === 200) {
|
||||
this.msgSuccess(response.msg)
|
||||
this.open = false
|
||||
this.getList()
|
||||
} else {
|
||||
this.msgError(response.msg)
|
||||
}
|
||||
}).catch(function() {})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="css">
|
||||
.panel .el-transfer__buttons{
|
||||
width: 150px;
|
||||
}
|
||||
.panel .el-transfer__buttons .el-button + .el-button{
|
||||
margin-left:0;
|
||||
}
|
||||
.panel .el-transfer-panel{
|
||||
width: 300px;
|
||||
}
|
||||
|
||||
.el-col {
|
||||
padding: 0 5px;
|
||||
}
|
||||
.el-drawer__header{
|
||||
margin-bottom: 0;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,314 @@
|
||||
<template>
|
||||
<BasicLayout>
|
||||
<template #wrapper>
|
||||
<el-card class="box-card">
|
||||
<el-form ref="queryForm" :model="queryParams" :inline="true" class="search-form">
|
||||
<el-form-item label="状态" prop="status">
|
||||
<el-select
|
||||
v-model="queryParams.status"
|
||||
placeholder="操作状态"
|
||||
clearable
|
||||
size="small"
|
||||
>
|
||||
<el-option
|
||||
v-for="dict in statusOptions"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="创建时间">
|
||||
<el-date-picker
|
||||
v-model="dateRange"
|
||||
size="small"
|
||||
type="datetimerange"
|
||||
:picker-options="pickerOptions"
|
||||
range-separator="至"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
align="right"
|
||||
value-format="yyyy-MM-dd HH:mm:ss"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" size="small" :icon="Search" @click="handleQuery">搜索</el-button>
|
||||
<el-button size="small" :icon="Refresh" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<div class="toolbar mb8">
|
||||
<el-button v-permisaction="['admin:sysOperLog:remove']" type="danger" size="small" :icon="Delete" :disabled="multiple" @click="handleDelete">删除</el-button>
|
||||
<el-button v-permisaction="['admin:sysOperLog:export']" size="small" :icon="Download" @click="handleExport">导出</el-button>
|
||||
</div>
|
||||
|
||||
<el-table v-loading="loading" :data="list" border stripe @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="编号" width="70" prop="id" />
|
||||
<el-table-column
|
||||
label="Request info"
|
||||
prop="operUrl"
|
||||
>
|
||||
<template #default="scope">
|
||||
<el-popover trigger="hover" placement="top">
|
||||
|
||||
<p>Request:
|
||||
<el-tag v-if="scope.row.requestMethod=='GET'">{{ scope.row.requestMethod }}</el-tag>
|
||||
<el-tag v-if="scope.row.requestMethod=='POST'" type="success">{{ scope.row.requestMethod }}</el-tag>
|
||||
<el-tag v-if="scope.row.requestMethod=='PUT'" type="warning">{{ scope.row.requestMethod }}</el-tag>
|
||||
<el-tag v-if="scope.row.requestMethod=='DELETE'" type="danger">{{ scope.row.requestMethod }}</el-tag>
|
||||
{{ scope.row.operUrl }}
|
||||
</p>
|
||||
<p>Host: {{ scope.row.operIp }}</p>
|
||||
<p>Location: {{ scope.row.operLocation }}</p>
|
||||
<p>耗时: {{ scope.row.latencyTime }}</p>
|
||||
<template #reference><div class="name-wrapper">
|
||||
<el-tag v-if="scope.row.requestMethod=='GET'">{{ scope.row.requestMethod }}</el-tag>
|
||||
<el-tag v-if="scope.row.requestMethod=='POST'" type="success">{{ scope.row.requestMethod }}</el-tag>
|
||||
<el-tag v-if="scope.row.requestMethod=='PUT'" type="warning">{{ scope.row.requestMethod }}</el-tag>
|
||||
<el-tag v-if="scope.row.requestMethod=='DELETE'" type="danger">{{ scope.row.requestMethod }}</el-tag>
|
||||
{{ scope.row.operUrl }}
|
||||
</div></template>
|
||||
</el-popover>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
label="操作人员"
|
||||
prop="operName"
|
||||
width="160"
|
||||
:show-overflow-tooltip="true"
|
||||
/>
|
||||
<el-table-column
|
||||
label="状态"
|
||||
prop="status"
|
||||
width="80"
|
||||
:show-overflow-tooltip="true"
|
||||
>
|
||||
<template #default="scope">
|
||||
<el-tag v-if="scope.row.status=='2'" type="success">{{ statusFormat(scope.row,scope.row.status) }}</el-tag>
|
||||
<el-tag v-if="scope.row.status=='1'" type="danger">{{ statusFormat(scope.row,scope.row.status) }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作日期" prop="operTime" width="160">
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.operTime) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
label="操作"
|
||||
width="80"
|
||||
class-name="small-padding fixed-width"
|
||||
>
|
||||
<template #default="scope">
|
||||
<el-button v-permisaction="['admin:sysOperLog:query']" type="primary" link size="small" @click="handleView(scope.row,scope.index)">详细</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<pagination
|
||||
v-show="total>0"
|
||||
v-model:current-page="queryParams.pageIndex"
|
||||
v-model:page-size="queryParams.pageSize"
|
||||
:total="total"
|
||||
@pagination="getList"
|
||||
/>
|
||||
|
||||
<!-- 操作日志详细 -->
|
||||
<el-dialog v-model="open" title="操作日志详细" width="700px" :close-on-click-modal="false">
|
||||
<el-form ref="form" :model="form" label-width="100px" size="mini">
|
||||
<el-row>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="请求地址:">{{ form.operUrl }}</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item
|
||||
label="登录信息:"
|
||||
>{{ form.operName }} / {{ form.operIp }} / {{ form.operLocation }}</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="12">
|
||||
<el-form-item label="请求方式:">{{ form.requestMethod }}</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="耗时:">{{ form.latencyTime }}</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="请求参数:">{{ form.operParam }}</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="返回参数:">{{ form.jsonResult }}</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="操作状态:">
|
||||
<div v-if="form.status === '2'">正常</div>
|
||||
<div v-else-if="form.status === '1'">关闭</div>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="操作时间:">{{ parseTime(form.operTime) }}</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item v-if="form.status === 1" label="异常信息:">{{ form.errorMsg }}</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<template #footer><div class="dialog-footer">
|
||||
<el-button @click="open = false">关 闭</el-button>
|
||||
</div></template>
|
||||
</el-dialog>
|
||||
</el-card>
|
||||
</template>
|
||||
</BasicLayout>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { listSysOperlog, delSysOperlog, cleanOperlog } from '@/api/admin/sys-opera-log'
|
||||
import { formatJson } from '@/utils'
|
||||
import { Search, Refresh, Delete, Download } from '@element-plus/icons-vue'
|
||||
|
||||
export default {
|
||||
name: 'SysOperLogManage',
|
||||
setup() {
|
||||
return { Search, Refresh, Delete, Download }
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 选中数组
|
||||
ids: [],
|
||||
// 非多个禁用
|
||||
multiple: true,
|
||||
// 总条数
|
||||
total: 0,
|
||||
// 表格数据
|
||||
list: [],
|
||||
// 是否显示弹出层
|
||||
open: false,
|
||||
// 类型数据字典
|
||||
statusOptions: [],
|
||||
// 日期范围
|
||||
dateRange: [],
|
||||
// 表单参数
|
||||
form: {},
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageIndex: 1,
|
||||
pageSize: 10,
|
||||
title: undefined,
|
||||
operName: undefined,
|
||||
businessType: undefined,
|
||||
status: undefined,
|
||||
createdAtOrder: 'desc'
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getList()
|
||||
|
||||
this.getDicts('sys_common_status').then(response => {
|
||||
this.statusOptions = response.data
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
/** 查询登录日志 */
|
||||
getList() {
|
||||
this.loading = true
|
||||
listSysOperlog(this.addDateRange(this.queryParams, this.dateRange)).then(response => {
|
||||
this.list = response.data.list
|
||||
this.total = response.data.count
|
||||
this.loading = false
|
||||
}
|
||||
)
|
||||
},
|
||||
// 操作日志状态字典翻译
|
||||
statusFormat(row, column) {
|
||||
return this.selectDictLabel(this.statusOptions, row.status)
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
this.queryParams.pageIndex = 1
|
||||
this.getList()
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.dateRange = []
|
||||
this.resetForm('queryForm')
|
||||
this.handleQuery()
|
||||
},
|
||||
// 多选框选中数据
|
||||
handleSelectionChange(selection) {
|
||||
this.ids = selection.map(item => item.id)
|
||||
this.multiple = !selection.length
|
||||
},
|
||||
/** 详细按钮操作 */
|
||||
handleView(row) {
|
||||
this.open = true
|
||||
this.form = row
|
||||
},
|
||||
/** 删除按钮操作 */
|
||||
handleDelete(row) {
|
||||
const operIds = (row.id && [row.id]) || this.ids
|
||||
this.$confirm('是否确认删除日志编号为"' + operIds + '"的数据项?', '警告', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(function() {
|
||||
return delSysOperlog({ 'ids': operIds })
|
||||
}).then((response) => {
|
||||
if (response.code === 200) {
|
||||
this.msgSuccess(response.msg)
|
||||
this.open = false
|
||||
this.getList()
|
||||
} else {
|
||||
this.msgError(response.msg)
|
||||
}
|
||||
}).catch(function() {})
|
||||
},
|
||||
/** 清空按钮操作 */
|
||||
handleClean() {
|
||||
this.$confirm('是否确认清空所有操作日志数据项?', '警告', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(function() {
|
||||
return cleanOperlog()
|
||||
}).then((response) => {
|
||||
if (response.code === 200) {
|
||||
this.msgSuccess(response.msg)
|
||||
this.open = false
|
||||
this.getList()
|
||||
} else {
|
||||
this.msgError(response.msg)
|
||||
}
|
||||
}).catch(function() {})
|
||||
},
|
||||
/** 导出按钮操作 */
|
||||
handleExport() {
|
||||
// const queryParams = this.queryParams
|
||||
this.$confirm('是否确认导出所有操作日志数据项?', '警告', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
this.downloadLoading = true
|
||||
import('@/vendor/Export2Excel').then(excel => {
|
||||
const tHeader = ['日志编号', '系统模块', '操作类型', '请求方式', '操作人员', '主机', '操作地点', '操作状态', '操作url', '操作日期']
|
||||
const filterVal = ['ID', 'title', 'businessType', 'method', 'operName', 'operIp', 'operLocation', 'status', 'operUrl', 'operTime']
|
||||
const list = this.list
|
||||
const data = formatJson(filterVal, list)
|
||||
excel.export_json_to_excel({
|
||||
header: tHeader,
|
||||
data,
|
||||
filename: '操作日志',
|
||||
autoWidth: true, // Optional
|
||||
bookType: 'xlsx' // Optional
|
||||
})
|
||||
this.downloadLoading = false
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -0,0 +1,319 @@
|
||||
<template>
|
||||
<BasicLayout>
|
||||
<template #wrapper>
|
||||
<el-card class="box-card">
|
||||
<el-form ref="queryForm" :model="queryParams" :inline="true" class="search-form">
|
||||
<el-form-item label="岗位编码" prop="postCode">
|
||||
<el-input
|
||||
v-model="queryParams.postCode"
|
||||
placeholder="请输入岗位编码"
|
||||
clearable
|
||||
size="small"
|
||||
@keyup.enter="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="岗位名称" prop="postName">
|
||||
<el-input
|
||||
v-model="queryParams.postName"
|
||||
placeholder="请输入岗位名称"
|
||||
clearable
|
||||
size="small"
|
||||
@keyup.enter="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="状态" prop="status">
|
||||
<el-select v-model="queryParams.status" placeholder="岗位状态" clearable size="small">
|
||||
<el-option
|
||||
v-for="dict in statusOptions"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" size="small" :icon="Search" @click="handleQuery">搜索</el-button>
|
||||
<el-button size="small" :icon="Refresh" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<div class="toolbar mb8">
|
||||
<el-button v-permisaction="['admin:sysPost:add']" type="primary" size="small" :icon="Plus" @click="handleAdd">新增</el-button>
|
||||
<el-button v-permisaction="['admin:sysPost:edit']" type="primary" size="small" :icon="Edit" :disabled="single" @click="handleUpdate">修改</el-button>
|
||||
<el-button v-permisaction="['admin:sysPost:remove']" type="danger" size="small" :icon="Delete" :disabled="multiple" @click="handleDelete">删除</el-button>
|
||||
<el-button v-permisaction="['admin:sysPost:export']" size="small" :icon="Download" @click="handleExport">导出</el-button>
|
||||
</div>
|
||||
|
||||
<el-table v-loading="loading" :data="postList" border stripe @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="岗位编号" width="80" align="center" prop="postId" />
|
||||
<el-table-column label="岗位编码" align="center" prop="postCode" />
|
||||
<el-table-column label="岗位名称" align="center" prop="postName" />
|
||||
<el-table-column label="岗位排序" align="center" prop="sort" />
|
||||
<el-table-column label="状态" align="center" prop="status" :formatter="statusFormat">
|
||||
<template #default="scope">
|
||||
<el-tag
|
||||
:type="scope.row.status === 1 ? 'danger' : 'success'"
|
||||
disable-transitions
|
||||
>{{ statusFormat(scope.row) }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="创建时间" align="center" prop="createdAt" width="180">
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.createdAt) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||
<template #default="scope">
|
||||
<el-button v-permisaction="['admin:sysPost:edit']" type="primary" link size="small" :icon="Edit" @click="handleUpdate(scope.row)">修改</el-button>
|
||||
<el-divider direction="vertical" />
|
||||
<el-button v-permisaction="['admin:sysPost:remove']" type="danger" link size="small" :icon="Delete" @click="handleDelete(scope.row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<pagination
|
||||
v-show="total>0"
|
||||
v-model:current-page="queryParams.pageIndex"
|
||||
v-model:page-size="queryParams.pageSize"
|
||||
:total="total"
|
||||
@pagination="getList"
|
||||
/>
|
||||
|
||||
<!-- 添加或修改岗位对话框 -->
|
||||
<el-dialog v-model="open" :title="title" width="500px" :close-on-click-modal="false">
|
||||
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
|
||||
<el-form-item label="岗位名称" prop="postName">
|
||||
<el-input v-model="form.postName" placeholder="请输入岗位名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="岗位编码" prop="postCode">
|
||||
<el-input v-model="form.postCode" placeholder="请输入编码名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="岗位顺序" prop="sort">
|
||||
<el-input-number v-model="form.sort" controls-position="right" :min="0" />
|
||||
</el-form-item>
|
||||
<el-form-item label="岗位状态" prop="status">
|
||||
<el-radio-group v-model="form.status">
|
||||
<el-radio
|
||||
v-for="dict in statusOptions"
|
||||
:key="dict.value"
|
||||
:label="dict.value"
|
||||
>{{ dict.label }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer><div class="dialog-footer">
|
||||
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
</div></template>
|
||||
</el-dialog>
|
||||
</el-card>
|
||||
</template>
|
||||
</BasicLayout>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { listPost, getPost, delPost, addPost, updatePost } from '@/api/admin/sys-post'
|
||||
import { formatJson } from '@/utils'
|
||||
import { Search, Refresh, Plus, Edit, Delete, Download } from '@element-plus/icons-vue'
|
||||
|
||||
export default {
|
||||
name: 'SysPostManage',
|
||||
setup() {
|
||||
return { Search, Refresh, Plus, Edit, Delete, Download }
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 选中数组
|
||||
ids: [],
|
||||
// 非单个禁用
|
||||
single: true,
|
||||
// 非多个禁用
|
||||
multiple: true,
|
||||
// 总条数
|
||||
total: 0,
|
||||
// 岗位表格数据
|
||||
postList: [],
|
||||
// 弹出层标题
|
||||
title: '',
|
||||
// 是否显示弹出层
|
||||
open: false,
|
||||
// 状态数据字典
|
||||
statusOptions: [],
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageIndex: 1,
|
||||
pageSize: 10,
|
||||
postCode: undefined,
|
||||
postName: undefined,
|
||||
status: undefined
|
||||
},
|
||||
// 表单参数
|
||||
form: {},
|
||||
// 表单校验
|
||||
rules: {
|
||||
postName: [
|
||||
{ required: true, message: '岗位名称不能为空', trigger: 'blur' }
|
||||
],
|
||||
postCode: [
|
||||
{ required: true, message: '岗位编码不能为空', trigger: 'blur' }
|
||||
],
|
||||
sort: [
|
||||
{ required: true, message: '岗位顺序不能为空', trigger: 'blur' }
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getList()
|
||||
this.getDicts('sys_normal_disable').then(response => {
|
||||
this.statusOptions = response.data
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
/** 查询岗位列表 */
|
||||
getList() {
|
||||
this.loading = true
|
||||
listPost(this.queryParams).then(response => {
|
||||
this.postList = response.data.list
|
||||
this.total = response.data.count
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
// 岗位状态字典翻译
|
||||
statusFormat(row) {
|
||||
return this.selectDictLabel(this.statusOptions, row.status)
|
||||
},
|
||||
// 取消按钮
|
||||
cancel() {
|
||||
this.open = false
|
||||
this.reset()
|
||||
},
|
||||
// 表单重置
|
||||
reset() {
|
||||
this.form = {
|
||||
postId: undefined,
|
||||
postCode: undefined,
|
||||
postName: undefined,
|
||||
sort: 0,
|
||||
status: '1',
|
||||
remark: undefined
|
||||
}
|
||||
this.resetForm('form')
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
this.queryParams.pageIndex = 1
|
||||
this.getList()
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.resetForm('queryForm')
|
||||
this.handleQuery()
|
||||
},
|
||||
// 多选框选中数据
|
||||
handleSelectionChange(selection) {
|
||||
this.ids = selection.map(item => item.postId)
|
||||
this.single = selection.length !== 1
|
||||
this.multiple = !selection.length
|
||||
},
|
||||
/** 新增按钮操作 */
|
||||
handleAdd() {
|
||||
this.reset()
|
||||
this.open = true
|
||||
this.title = '添加岗位'
|
||||
},
|
||||
/** 修改按钮操作 */
|
||||
handleUpdate(row) {
|
||||
this.reset()
|
||||
|
||||
const postId = row.postId || this.ids
|
||||
getPost(postId).then(response => {
|
||||
this.form = response.data
|
||||
this.form.status = String(this.form.status)
|
||||
this.open = true
|
||||
this.title = '修改岗位'
|
||||
})
|
||||
},
|
||||
/** 提交按钮 */
|
||||
submitForm: function() {
|
||||
this.$refs['form'].validate(valid => {
|
||||
if (valid) {
|
||||
this.form.status = parseInt(this.form.status)
|
||||
if (this.form.postId !== undefined) {
|
||||
updatePost(this.form, this.form.postId).then(response => {
|
||||
if (response.code === 200) {
|
||||
this.msgSuccess(response.msg)
|
||||
this.open = false
|
||||
this.getList()
|
||||
} else {
|
||||
this.msgError(response.msg)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
addPost(this.form).then(response => {
|
||||
if (response.code === 200) {
|
||||
this.msgSuccess(response.msg)
|
||||
this.open = false
|
||||
this.getList()
|
||||
} else {
|
||||
this.msgError(response.msg)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
/** 删除按钮操作 */
|
||||
handleDelete(row) {
|
||||
// const postIds = row.postId || this.ids
|
||||
const Ids = (row.postId && [row.postId]) || this.ids
|
||||
this.$confirm('是否确认删除岗位编号为"' + Ids + '"的数据项?', '警告', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(function() {
|
||||
return delPost({ 'ids': Ids })
|
||||
}).then((response) => {
|
||||
if (response.code === 200) {
|
||||
this.msgSuccess(response.msg)
|
||||
this.open = false
|
||||
this.getList()
|
||||
} else {
|
||||
this.msgError(response.msg)
|
||||
}
|
||||
}).catch(function() {})
|
||||
},
|
||||
/** 导出按钮操作 */
|
||||
handleExport() {
|
||||
// const queryParams = this.queryParams
|
||||
this.$confirm('是否确认导出所有岗位数据项?', '警告', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
this.downloadLoading = true
|
||||
import('@/vendor/Export2Excel').then(excel => {
|
||||
const tHeader = ['岗位编号', '岗位编码', '岗位名称', '排序', '创建时间']
|
||||
const filterVal = ['postId', 'postCode', 'postName', 'sort', 'createdAt']
|
||||
const list = this.postList
|
||||
const data = formatJson(filterVal, list)
|
||||
excel.export_json_to_excel({
|
||||
header: tHeader,
|
||||
data,
|
||||
filename: '岗位管理',
|
||||
autoWidth: true, // Optional
|
||||
bookType: 'xlsx' // Optional
|
||||
})
|
||||
this.downloadLoading = false
|
||||
})
|
||||
}).catch(function() {})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,552 @@
|
||||
<template>
|
||||
<BasicLayout>
|
||||
<template #wrapper>
|
||||
<el-card class="box-card">
|
||||
<el-form ref="queryForm" :model="queryParams" :inline="true" class="search-form">
|
||||
<el-form-item label="名称" prop="roleName">
|
||||
<el-input
|
||||
v-model="queryParams.roleName"
|
||||
placeholder="请输入角色名称"
|
||||
clearable
|
||||
size="small"
|
||||
@keyup.enter="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="权限字符" prop="roleKey">
|
||||
<el-input
|
||||
v-model="queryParams.roleKey"
|
||||
placeholder="请输入权限字符"
|
||||
clearable
|
||||
size="small"
|
||||
@keyup.enter="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="状态" prop="status">
|
||||
<el-select
|
||||
v-model="queryParams.status"
|
||||
placeholder="角色状态"
|
||||
clearable
|
||||
size="small"
|
||||
>
|
||||
<el-option
|
||||
v-for="dict in statusOptions"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" size="small" :icon="Search" @click="handleQuery">搜索</el-button>
|
||||
<el-button size="small" :icon="Refresh" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<div class="toolbar mb8">
|
||||
<el-button v-permisaction="['admin:sysRole:add']" type="primary" size="small" :icon="Plus" @click="handleAdd">新增</el-button>
|
||||
<el-button v-permisaction="['admin:sysRole:update']" type="primary" size="small" :icon="Edit" :disabled="single" @click="handleUpdate">修改</el-button>
|
||||
<el-button v-permisaction="['admin:sysRole:remove']" type="danger" size="small" :icon="Delete" :disabled="multiple" @click="handleDelete">删除</el-button>
|
||||
<el-button v-permisaction="['admin:sysRole:export']" size="small" :icon="Download" @click="handleExport">导出</el-button>
|
||||
</div>
|
||||
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
:data="roleList"
|
||||
border
|
||||
stripe
|
||||
@selection-change="handleSelectionChange"
|
||||
@sort-change="handleSortChang"
|
||||
>
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="编码" sortable="custom" prop="roleId" width="80" />
|
||||
<el-table-column label="名称" sortable="custom" prop="roleName" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="权限字符" prop="roleKey" :show-overflow-tooltip="true" width="150" />
|
||||
<el-table-column label="排序" sortable="custom" prop="roleSort" width="80" />
|
||||
<el-table-column label="状态" sortable="custom" width="80">
|
||||
<template #default="scope">
|
||||
<el-switch
|
||||
v-model="scope.row.status"
|
||||
active-value="2"
|
||||
inactive-value="1"
|
||||
@change="handleStatusChange(scope.row)"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="创建时间" sortable="custom" prop="createdAt" width="160">
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.createdAt) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
label="操作"
|
||||
align="left"
|
||||
class-name="small-padding fixed-width"
|
||||
width="220"
|
||||
>
|
||||
<template #default="scope">
|
||||
<el-button v-permisaction="['admin:sysRole:update']" type="primary" link size="small" :icon="Edit" @click="handleUpdate(scope.row)">修改</el-button>
|
||||
<el-divider direction="vertical" />
|
||||
<el-button v-permisaction="['admin:sysRole:update']" type="primary" link size="small" @click="handleDataScope(scope.row)">数据权限</el-button>
|
||||
<template v-if="scope.row.roleKey!=='admin'">
|
||||
<el-divider direction="vertical" />
|
||||
<el-button v-permisaction="['admin:sysRole:remove']" type="danger" link size="small" :icon="Delete" @click="handleDelete(scope.row)">删除</el-button>
|
||||
</template>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<pagination
|
||||
v-show="total>0"
|
||||
v-model:current-page="queryParams.pageIndex"
|
||||
v-model:page-size="queryParams.pageSize"
|
||||
:total="total"
|
||||
@pagination="getList"
|
||||
/>
|
||||
|
||||
<!-- 添加或修改角色配置对话框 -->
|
||||
<el-dialog v-if="open" v-model="open" :title="title" width="500px" :close-on-click-modal="false">
|
||||
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
|
||||
<el-form-item label="角色名称" prop="roleName">
|
||||
<el-input v-model="form.roleName" placeholder="请输入角色名称" :disabled="isEdit" />
|
||||
</el-form-item>
|
||||
<el-form-item label="权限字符" prop="roleKey">
|
||||
<el-input v-model="form.roleKey" placeholder="请输入权限字符" :disabled="isEdit" />
|
||||
</el-form-item>
|
||||
<el-form-item label="角色顺序" prop="roleSort">
|
||||
<el-input-number v-model="form.roleSort" controls-position="right" :min="0" />
|
||||
</el-form-item>
|
||||
<el-form-item label="状态">
|
||||
<el-radio-group v-model="form.status">
|
||||
<el-radio
|
||||
v-for="dict in statusOptions"
|
||||
:key="dict.value"
|
||||
:label="dict.value"
|
||||
>{{ dict.label }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="菜单权限">
|
||||
<el-tree
|
||||
ref="menuTree"
|
||||
:data="menuOptions"
|
||||
show-checkbox
|
||||
node-key="id"
|
||||
:empty-text="menuOptionsAlert"
|
||||
style="height:171px;overflow-y:auto;overflow-x:hidden;"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="备注">
|
||||
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer><div class="dialog-footer">
|
||||
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
</div></template>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 分配角色数据权限对话框 -->
|
||||
<el-dialog v-if="openDataScope" v-model="open" :title="title" width="500px" :close-on-click-modal="false">
|
||||
<el-form :model="form" label-width="80px">
|
||||
<el-form-item label="角色名称">
|
||||
<el-input v-model="form.roleName" :disabled="true" />
|
||||
</el-form-item>
|
||||
<el-form-item label="权限字符">
|
||||
<el-input v-model="form.roleKey" :disabled="true" />
|
||||
</el-form-item>
|
||||
<el-form-item label="权限范围">
|
||||
<el-select v-model="form.dataScope">
|
||||
<el-option
|
||||
v-for="item in dataScopeOptions"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item v-show="form.dataScope == 2" label="数据权限">
|
||||
<el-tree
|
||||
ref="dept"
|
||||
:data="deptOptions"
|
||||
show-checkbox
|
||||
default-expand-all
|
||||
node-key="id"
|
||||
empty-text="加载中,请稍后"
|
||||
:props="defaultProps"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer><div class="dialog-footer">
|
||||
<el-button type="primary" @click="submitDataScope">确 定</el-button>
|
||||
<el-button @click="cancelDataScope">取 消</el-button>
|
||||
</div></template>
|
||||
</el-dialog>
|
||||
</el-card>
|
||||
</template>
|
||||
</BasicLayout>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { listRole, getRole, delRole, addRole, updateRole, dataScope, changeRoleStatus } from '@/api/admin/sys-role'
|
||||
import { roleMenuTreeselect } from '@/api/admin/sys-menu'
|
||||
import { treeselect as deptTreeselect, roleDeptTreeselect } from '@/api/admin/sys-dept'
|
||||
import { formatJson } from '@/utils'
|
||||
import { Search, Refresh, Plus, Edit, Delete, Download } from '@element-plus/icons-vue'
|
||||
|
||||
export default {
|
||||
name: 'RoleManagement',
|
||||
components: {
|
||||
|
||||
},
|
||||
setup() {
|
||||
return { Search, Refresh, Plus, Edit, Delete, Download }
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 选中数组
|
||||
ids: [],
|
||||
// 非单个禁用
|
||||
single: true,
|
||||
// 非多个禁用
|
||||
multiple: true,
|
||||
// 总条数
|
||||
total: 0,
|
||||
// 角色表格数据
|
||||
roleList: [],
|
||||
menuIdsChecked: [],
|
||||
// 弹出层标题
|
||||
title: '',
|
||||
// 是否显示弹出层
|
||||
open: false,
|
||||
// 是否显示弹出层(数据权限)
|
||||
openDataScope: false,
|
||||
isEdit: false,
|
||||
// 日期范围
|
||||
dateRange: [],
|
||||
// 状态数据字典
|
||||
statusOptions: [],
|
||||
// 数据范围选项
|
||||
dataScopeOptions: [
|
||||
{
|
||||
value: '1',
|
||||
label: '全部数据权限'
|
||||
},
|
||||
{
|
||||
value: '2',
|
||||
label: '自定数据权限'
|
||||
},
|
||||
{
|
||||
value: '3',
|
||||
label: '本部门数据权限'
|
||||
},
|
||||
{
|
||||
value: '4',
|
||||
label: '本部门及以下数据权限'
|
||||
},
|
||||
{
|
||||
value: '5',
|
||||
label: '仅本人数据权限'
|
||||
}
|
||||
],
|
||||
// 菜单列表
|
||||
menuOptions: [],
|
||||
menuList: [],
|
||||
// 部门列表
|
||||
deptOptions: [],
|
||||
menuOptionsAlert: '加载中,请稍后',
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageIndex: 1,
|
||||
pageSize: 10,
|
||||
roleName: undefined,
|
||||
roleKey: undefined,
|
||||
status: undefined
|
||||
},
|
||||
// 表单参数
|
||||
form: {
|
||||
sysMenu: []
|
||||
},
|
||||
defaultProps: {
|
||||
children: 'children',
|
||||
label: 'label'
|
||||
},
|
||||
// 表单校验
|
||||
rules: {
|
||||
roleName: [
|
||||
{ required: true, message: '角色名称不能为空', trigger: 'blur' }
|
||||
],
|
||||
roleKey: [
|
||||
{ required: true, message: '权限字符不能为空', trigger: 'blur' }
|
||||
],
|
||||
roleSort: [
|
||||
{ required: true, message: '角色顺序不能为空', trigger: 'blur' }
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getList()
|
||||
this.getMenuTreeselect()
|
||||
this.getDicts('sys_normal_disable').then(response => {
|
||||
this.statusOptions = response.data
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
/** 查询角色列表 */
|
||||
getList() {
|
||||
this.loading = true
|
||||
listRole(this.addDateRange(this.queryParams, this.dateRange)).then(
|
||||
response => {
|
||||
this.roleList = response.data.list
|
||||
this.total = response.data.count
|
||||
this.loading = false
|
||||
}
|
||||
)
|
||||
},
|
||||
/** 查询菜单树结构 */
|
||||
getMenuTreeselect() {
|
||||
roleMenuTreeselect(0).then(response => {
|
||||
this.menuOptions = response.data.menus
|
||||
this.menuList = this.menuOptions
|
||||
})
|
||||
},
|
||||
/** 查询部门树结构 */
|
||||
getDeptTreeselect() {
|
||||
deptTreeselect().then(response => {
|
||||
this.deptOptions = response.data.list
|
||||
})
|
||||
},
|
||||
// 所有菜单节点数据
|
||||
getMenuAllCheckedKeys() {
|
||||
// 目前被选中的菜单节点
|
||||
const checkedKeys = this.$refs.menuTree.getHalfCheckedKeys()
|
||||
console.log('目前被选中的菜单节点', checkedKeys)
|
||||
// 半选中的菜单节点
|
||||
const halfCheckedKeys = this.$refs.menuTree.getCheckedKeys()
|
||||
console.log('半选中的菜单节点', halfCheckedKeys)
|
||||
// checkedKeys.unshift.apply(checkedKeys, halfCheckedKeys)
|
||||
return halfCheckedKeys
|
||||
},
|
||||
// 所有部门节点数据
|
||||
getDeptAllCheckedKeys() {
|
||||
// 目前被选中的部门节点
|
||||
const checkedKeys = this.$refs.dept.getCheckedKeys()
|
||||
// 半选中的部门节点
|
||||
// const halfCheckedKeys = this.$refs.dept.getCheckedKeys()
|
||||
// checkedKeys.unshift.apply(checkedKeys, halfCheckedKeys)
|
||||
return checkedKeys
|
||||
},
|
||||
/** 根据角色ID查询菜单树结构 */
|
||||
getRoleMenuTreeselect(row, checkedKeys) {
|
||||
if (row.roleKey === 'admin') {
|
||||
this.menuOptionsAlert = '系统超级管理员无需此操作'
|
||||
this.menuOptions = []
|
||||
} else {
|
||||
this.$nextTick(() => {
|
||||
this.$refs.menuTree.setCheckedKeys(checkedKeys)
|
||||
})
|
||||
}
|
||||
},
|
||||
/** 根据角色ID查询部门树结构 */
|
||||
getRoleDeptTreeselect(roleId) {
|
||||
roleDeptTreeselect(roleId).then(response => {
|
||||
this.deptOptions = response.data.depts
|
||||
this.$nextTick(() => {
|
||||
this.$refs.dept.setCheckedKeys(response.data.checkedKeys)
|
||||
})
|
||||
})
|
||||
},
|
||||
// 角色状态修改
|
||||
handleStatusChange(row) {
|
||||
const text = row.status === '2' ? '启用' : '停用'
|
||||
this.$confirm('确认要"' + text + '""' + row.roleName + '"角色吗?', '警告', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(function() {
|
||||
return changeRoleStatus(row.roleId, row.status)
|
||||
}).then((res) => {
|
||||
console.log('res', res)
|
||||
this.msgSuccess(res.msg)
|
||||
}).catch(function() {
|
||||
row.status = row.status === '2' ? '1' : '2'
|
||||
})
|
||||
},
|
||||
// 取消按钮
|
||||
cancel() {
|
||||
this.open = false
|
||||
this.reset()
|
||||
},
|
||||
// 取消按钮(数据权限)
|
||||
cancelDataScope() {
|
||||
this.openDataScope = false
|
||||
this.reset()
|
||||
},
|
||||
// 表单重置
|
||||
reset() {
|
||||
this.menuOptions = this.menuList
|
||||
if (this.$refs.menuTree !== undefined) {
|
||||
this.$refs.menuTree.setCheckedKeys([])
|
||||
}
|
||||
this.form = {
|
||||
roleId: undefined,
|
||||
roleName: undefined,
|
||||
roleKey: undefined,
|
||||
roleSort: 0,
|
||||
status: '2',
|
||||
menuIds: [],
|
||||
deptIds: [],
|
||||
sysMenu: [],
|
||||
remark: undefined
|
||||
}
|
||||
this.resetForm('form')
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
this.queryParams.pageIndex = 1
|
||||
this.getList()
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.dateRange = []
|
||||
this.resetForm('queryForm')
|
||||
this.handleQuery()
|
||||
},
|
||||
// 多选框选中数据
|
||||
handleSelectionChange(selection) {
|
||||
this.ids = selection.map(item => item.roleId)
|
||||
this.single = selection.length !== 1
|
||||
this.multiple = !selection.length
|
||||
},
|
||||
/** 新增按钮操作 */
|
||||
handleAdd() {
|
||||
this.reset()
|
||||
// this.getMenuTreeselect(0)
|
||||
this.open = true
|
||||
this.title = '添加角色'
|
||||
this.isEdit = false
|
||||
},
|
||||
handleSortChang(column, prop, order) {
|
||||
prop = column.prop
|
||||
order = column.order
|
||||
if (order === 'descending') {
|
||||
this.queryParams[prop + 'Order'] = 'desc'
|
||||
} else if (order === 'ascending') {
|
||||
this.queryParams[prop + 'Order'] = 'asc'
|
||||
} else {
|
||||
this.queryParams[prop + 'Order'] = undefined
|
||||
}
|
||||
this.getList()
|
||||
},
|
||||
/** 修改按钮操作 */
|
||||
handleUpdate(row) {
|
||||
this.menuIdsChecked = []
|
||||
this.reset()
|
||||
const roleId = row.roleId || this.ids
|
||||
getRole(roleId).then(response => {
|
||||
this.form = response.data
|
||||
this.menuIdsChecked = response.data.menuIds
|
||||
this.title = '修改角色'
|
||||
this.isEdit = true
|
||||
this.open = true
|
||||
this.getRoleMenuTreeselect(row, response.data.menuIds)
|
||||
})
|
||||
},
|
||||
/** 分配数据权限操作 */
|
||||
handleDataScope(row) {
|
||||
this.reset()
|
||||
getRole(row.roleId).then(response => {
|
||||
this.form = response.data
|
||||
this.openDataScope = true
|
||||
this.title = '分配数据权限'
|
||||
this.getRoleDeptTreeselect(row.roleId)
|
||||
})
|
||||
},
|
||||
/** 提交按钮 */
|
||||
submitForm: function() {
|
||||
this.$refs['form'].validate(valid => {
|
||||
if (valid) {
|
||||
if (this.form.roleId !== undefined) {
|
||||
this.form.menuIds = this.getMenuAllCheckedKeys()
|
||||
updateRole(this.form, this.form.roleId).then(response => {
|
||||
if (response.code === 200) {
|
||||
this.msgSuccess(response.msg)
|
||||
this.open = false
|
||||
this.getList()
|
||||
} else {
|
||||
this.msgError(response.msg)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
this.form.menuIds = this.getMenuAllCheckedKeys()
|
||||
addRole(this.form).then(response => {
|
||||
if (response.code === 200) {
|
||||
this.msgSuccess(response.msg)
|
||||
this.open = false
|
||||
this.getList()
|
||||
} else {
|
||||
this.msgError(response.msg)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
/** 提交按钮(数据权限) */
|
||||
submitDataScope: function() {
|
||||
if (this.form.roleId !== undefined) {
|
||||
this.form.deptIds = this.getDeptAllCheckedKeys()
|
||||
console.log(this.getDeptAllCheckedKeys())
|
||||
dataScope(this.form).then(response => {
|
||||
if (response.code === 200) {
|
||||
this.msgSuccess(response.msg)
|
||||
this.openDataScope = false
|
||||
this.getList()
|
||||
} else {
|
||||
this.msgError(response.msg)
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
/** 删除按钮操作 */
|
||||
handleDelete(row) {
|
||||
const roleIds = (row.roleId && [row.roleId]) || this.ids
|
||||
this.$confirm('是否确认删除角色编号为"' + roleIds + '"的数据项?', '警告', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(function() {
|
||||
return delRole({ 'ids': roleIds })
|
||||
}).then((response) => {
|
||||
this.getList()
|
||||
this.msgSuccess(response.msg)
|
||||
}).catch(function() {})
|
||||
},
|
||||
/** 导出按钮操作 */
|
||||
handleExport() {
|
||||
this.$confirm('是否确认导出所有角色数据项?', '警告', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
this.downloadLoading = true
|
||||
import('@/vendor/Export2Excel').then(excel => {
|
||||
const tHeader = ['角色编号', '角色名称', '权限字符', '显示顺序', '状态', '创建时间']
|
||||
const filterVal = ['roleId', 'roleName', 'roleKey', 'roleSort', 'status', 'createdAt']
|
||||
const list = this.roleList
|
||||
const data = formatJson(filterVal, list)
|
||||
excel.export_json_to_excel({
|
||||
header: tHeader,
|
||||
data,
|
||||
filename: '角色管理',
|
||||
autoWidth: true, // Optional
|
||||
bookType: 'xlsx' // Optional
|
||||
})
|
||||
this.downloadLoading = false
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,683 @@
|
||||
<template>
|
||||
<BasicLayout>
|
||||
<template #wrapper>
|
||||
<el-card class="box-card">
|
||||
<el-row :gutter="20">
|
||||
<!--部门数据-->
|
||||
<el-col :span="4" :xs="24">
|
||||
<div class="head-container">
|
||||
<el-input
|
||||
v-model="deptName"
|
||||
placeholder="请输入部门名称"
|
||||
clearable
|
||||
size="small"
|
||||
|
||||
style="margin-bottom: 20px"
|
||||
/>
|
||||
</div>
|
||||
<div class="head-container">
|
||||
<el-tree
|
||||
ref="tree"
|
||||
:data="deptOptions"
|
||||
:props="defaultProps"
|
||||
:expand-on-click-node="false"
|
||||
:filter-node-method="filterNode"
|
||||
default-expand-all
|
||||
@node-click="handleNodeClick"
|
||||
/>
|
||||
</div>
|
||||
</el-col>
|
||||
<!--用户数据-->
|
||||
<el-col :span="20" :xs="24">
|
||||
<el-form ref="queryForm" :model="queryParams" :inline="true" label-width="68px">
|
||||
<el-form-item label="用户名称" prop="username">
|
||||
<el-input
|
||||
v-model="queryParams.username"
|
||||
placeholder="请输入用户名称"
|
||||
clearable
|
||||
size="small"
|
||||
style="width: 160px"
|
||||
@keyup.enter="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="手机号码" prop="phone">
|
||||
<el-input
|
||||
v-model="queryParams.phone"
|
||||
placeholder="请输入手机号码"
|
||||
clearable
|
||||
size="small"
|
||||
style="width: 160px"
|
||||
@keyup.enter="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="状态" prop="status">
|
||||
<el-select
|
||||
v-model="queryParams.status"
|
||||
placeholder="用户状态"
|
||||
clearable
|
||||
size="small"
|
||||
style="width: 160px"
|
||||
>
|
||||
<el-option
|
||||
v-for="dict in statusOptions"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" size="mini" @click="handleQuery">搜索</el-button>
|
||||
<el-button size="mini" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
v-permisaction="['admin:sysUser:add']"
|
||||
type="primary"
|
||||
|
||||
size="mini"
|
||||
@click="handleAdd"
|
||||
>新增</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
v-permisaction="['admin:sysUser:edit']"
|
||||
type="success"
|
||||
|
||||
size="mini"
|
||||
:disabled="single"
|
||||
@click="handleUpdate"
|
||||
>修改</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
v-permisaction="['admin:sysUser:remove']"
|
||||
type="danger"
|
||||
|
||||
size="mini"
|
||||
:disabled="multiple"
|
||||
@click="handleDelete"
|
||||
>删除</el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
:data="userList"
|
||||
border
|
||||
@selection-change="handleSelectionChange"
|
||||
@sort-change="handleSortChang"
|
||||
>
|
||||
<el-table-column type="selection" width="45" align="center" />
|
||||
<el-table-column label="编号" width="75" prop="userId" sortable="custom" />
|
||||
<el-table-column label="登录名" width="105" prop="username" sortable="custom" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="昵称" prop="nickName" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="部门" prop="dept.deptName" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="手机号" prop="phone" width="108" />
|
||||
<el-table-column label="状态" width="80" sortable="custom">
|
||||
<template #default="scope">
|
||||
<el-switch
|
||||
v-model="scope.row.status"
|
||||
active-value="2"
|
||||
inactive-value="1"
|
||||
@change="handleStatusChange(scope.row)"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
label="创建时间"
|
||||
prop="createdAt"
|
||||
sortable="custom"
|
||||
width="155"
|
||||
>
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.createdAt) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
label="操作"
|
||||
width="160"
|
||||
|
||||
fix="right"
|
||||
class-name="small-padding fixed-width"
|
||||
>
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
v-permisaction="['admin:sysUser:edit']"
|
||||
size="mini"
|
||||
type="text"
|
||||
|
||||
@click="handleUpdate(scope.row)"
|
||||
>修改</el-button>
|
||||
<el-button
|
||||
v-if="scope.row.userId !== 1"
|
||||
v-permisaction="['admin:sysUser:remove']"
|
||||
size="mini"
|
||||
type="text"
|
||||
|
||||
@click="handleDelete(scope.row)"
|
||||
>删除</el-button>
|
||||
<el-button
|
||||
v-permisaction="['admin:sysUser:resetPassword']"
|
||||
size="mini"
|
||||
type="text"
|
||||
|
||||
@click="handleResetPwd(scope.row)"
|
||||
>重置</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<pagination
|
||||
v-show="total>0"
|
||||
v-model:current-page="queryParams.pageIndex"
|
||||
v-model:page-size="queryParams.pageSize"
|
||||
:total="total"
|
||||
@pagination="getList"
|
||||
/>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
<!-- 添加或修改参数配置对话框 -->
|
||||
<el-dialog v-model="open" :title="title" width="600px" :close-on-click-modal="false">
|
||||
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="用户昵称" prop="nickName">
|
||||
<el-input v-model="form.nickName" placeholder="请输入用户昵称" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="归属部门" prop="deptId">
|
||||
<treeselect
|
||||
v-model="form.deptId"
|
||||
:options="deptOptions"
|
||||
placeholder="请选择归属部门"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="手机号码" prop="phone">
|
||||
<el-input v-model="form.phone" placeholder="请输入手机号码" maxlength="11" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="邮箱" prop="email">
|
||||
<el-input v-model="form.email" placeholder="请输入邮箱" maxlength="50" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="用户名称" prop="username">
|
||||
<el-input v-model="form.username" placeholder="请输入用户名称" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item v-if="form.userId == undefined" label="用户密码" prop="password">
|
||||
<el-input v-model="form.password" placeholder="请输入用户密码" type="password" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="用户性别">
|
||||
<el-select v-model="form.sex" placeholder="请选择">
|
||||
<el-option
|
||||
v-for="dict in sexOptions"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="状态">
|
||||
<el-radio-group v-model="form.status">
|
||||
<el-radio
|
||||
v-for="dict in statusOptions"
|
||||
:key="dict.value"
|
||||
:label="dict.value"
|
||||
>{{ dict.label }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="12">
|
||||
<el-form-item label="岗位">
|
||||
<el-select v-model="form.postId" placeholder="请选择" @change="$forceUpdate()">
|
||||
<el-option
|
||||
v-for="item in postOptions"
|
||||
:key="item.postId"
|
||||
:label="item.postName"
|
||||
:value="item.postId"
|
||||
:disabled="item.status == 1"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="角色">
|
||||
<el-select v-model="form.roleId" placeholder="请选择" @change="$forceUpdate()">
|
||||
<el-option
|
||||
v-for="item in roleOptions"
|
||||
:key="item.roleId"
|
||||
:label="item.roleName"
|
||||
:value="item.roleId"
|
||||
:disabled="item.status == 1"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="备注">
|
||||
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<template #footer><div class="dialog-footer">
|
||||
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
</div></template>
|
||||
</el-dialog>
|
||||
<!-- 用户导入对话框 -->
|
||||
<el-dialog v-model="open" :title="upload.title" width="400px" :close-on-click-modal="false">
|
||||
<el-upload
|
||||
ref="upload"
|
||||
:limit="1"
|
||||
accept=".xlsx, .xls"
|
||||
:headers="upload.headers"
|
||||
:action="upload.url + '?updateSupport=' + upload.updateSupport"
|
||||
:disabled="upload.isUploading"
|
||||
:on-progress="handleFileUploadProgress"
|
||||
:on-success="handleFileSuccess"
|
||||
:auto-upload="false"
|
||||
drag
|
||||
>
|
||||
<i class="ri-upload-line" />
|
||||
<div class="el-upload__text">
|
||||
将文件拖到此处,或
|
||||
<em>点击上传</em>
|
||||
</div>
|
||||
<template #tip>
|
||||
<div class="el-upload__tip">
|
||||
<el-checkbox v-model="upload.updateSupport" />是否更新已经存在的用户数据
|
||||
<el-link type="info" style="font-size:12px" @click="importTemplate">下载模板</el-link>
|
||||
</div>
|
||||
<div class="el-upload__tip" style="color:red">提示:仅允许导入"xls"或"xlsx"格式文件!</div>
|
||||
</template>
|
||||
</el-upload>
|
||||
<template #footer><div class="dialog-footer">
|
||||
<el-button type="primary" @click="submitFileForm">确 定</el-button>
|
||||
<el-button @click="upload.open = false">取 消</el-button>
|
||||
</div></template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
</BasicLayout>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { listUser, getUser, delUser, addUser, updateUser, exportUser, resetUserPwd, changeUserStatus, importTemplate } from '@/api/admin/sys-user'
|
||||
import { getToken } from '@/utils/auth'
|
||||
|
||||
import { listPost } from '@/api/admin/sys-post'
|
||||
import { listRole } from '@/api/admin/sys-role'
|
||||
import { treeselect } from '@/api/admin/sys-dept'
|
||||
|
||||
import Treeselect from 'vue3-treeselect'
|
||||
import 'vue3-treeselect/dist/vue3-treeselect.css'
|
||||
|
||||
export default {
|
||||
name: 'SysUserManage',
|
||||
components: { Treeselect },
|
||||
data() {
|
||||
return {
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 选中数组
|
||||
ids: [],
|
||||
// 非单个禁用
|
||||
single: true,
|
||||
// 非多个禁用
|
||||
multiple: true,
|
||||
// 总条数
|
||||
total: 0,
|
||||
// 用户表格数据
|
||||
userList: null,
|
||||
// 弹出层标题
|
||||
title: '',
|
||||
// 部门树选项
|
||||
deptOptions: undefined,
|
||||
// 是否显示弹出层
|
||||
open: false,
|
||||
// 部门名称
|
||||
deptName: undefined,
|
||||
// 默认密码
|
||||
initPassword: undefined,
|
||||
// 日期范围
|
||||
dateRange: [],
|
||||
// 状态数据字典
|
||||
statusOptions: [],
|
||||
// 性别状态字典
|
||||
sexOptions: [],
|
||||
// 岗位选项
|
||||
postOptions: [],
|
||||
// 角色选项
|
||||
roleOptions: [],
|
||||
// 表单参数
|
||||
form: {},
|
||||
defaultProps: {
|
||||
children: 'children',
|
||||
label: 'label'
|
||||
},
|
||||
// 用户导入参数
|
||||
upload: {
|
||||
// 是否显示弹出层(用户导入)
|
||||
open: false,
|
||||
// 弹出层标题(用户导入)
|
||||
title: '',
|
||||
// 是否禁用上传
|
||||
isUploading: false,
|
||||
// 是否更新已经存在的用户数据
|
||||
updateSupport: 0,
|
||||
// 设置上传的请求头部
|
||||
headers: { Authorization: 'Bearer ' + getToken() },
|
||||
// 上传的地址
|
||||
url: process.env.VUE_APP_BASE_API + '/system/user/importData'
|
||||
},
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageIndex: 1,
|
||||
pageSize: 10,
|
||||
username: undefined,
|
||||
phone: undefined,
|
||||
status: undefined,
|
||||
deptId: undefined
|
||||
},
|
||||
// 表单校验
|
||||
rules: {
|
||||
username: [{ required: true, message: '用户名称不能为空', trigger: 'blur' }],
|
||||
nickName: [{ required: true, message: '用户昵称不能为空', trigger: 'blur' }],
|
||||
deptId: [{ required: true, message: '归属部门不能为空', trigger: 'blur' }],
|
||||
password: [{ required: true, message: '用户密码不能为空', trigger: 'blur' }],
|
||||
email: [
|
||||
{ required: true, message: '邮箱地址不能为空', trigger: 'blur' },
|
||||
{ type: 'email', message: "'请输入正确的邮箱地址", trigger: ['blur', 'change'] }
|
||||
],
|
||||
phone: [
|
||||
{ required: true, message: '手机号码不能为空', trigger: 'blur' },
|
||||
{ pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/, message: '请输入正确的手机号码', trigger: 'blur' }
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
// 根据名称筛选部门树
|
||||
deptName(val) {
|
||||
this.$refs.tree.filter(val)
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getList()
|
||||
this.getTreeselect()
|
||||
this.getDicts('sys_normal_disable').then(response => {
|
||||
this.statusOptions = response.data
|
||||
})
|
||||
this.getDicts('sys_user_sex').then(response => {
|
||||
this.sexOptions = response.data
|
||||
})
|
||||
this.getConfigKey('sys_user_initPassword').then(response => {
|
||||
this.initPassword = response.data.configValue
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
/** 查询用户列表 */
|
||||
getList() {
|
||||
this.loading = true
|
||||
listUser(this.addDateRange(this.queryParams, this.dateRange)).then(response => {
|
||||
this.userList = response.data.list
|
||||
this.total = response.data.count
|
||||
this.loading = false
|
||||
}
|
||||
)
|
||||
},
|
||||
/** 查询部门下拉树结构 */
|
||||
getTreeselect() {
|
||||
treeselect().then(response => {
|
||||
this.deptOptions = response.data
|
||||
})
|
||||
},
|
||||
// 筛选节点
|
||||
filterNode(value, data) {
|
||||
if (!value) return true
|
||||
return data.label.indexOf(value) !== -1
|
||||
},
|
||||
// 节点单击事件
|
||||
handleNodeClick(data) {
|
||||
this.queryParams.deptId = '/' + data.id + '/'
|
||||
this.getList()
|
||||
},
|
||||
/** 转换菜单数据结构 */
|
||||
normalizer(node) {
|
||||
if (node.children && !node.children.length) {
|
||||
delete node.children
|
||||
}
|
||||
return {
|
||||
id: node.id,
|
||||
label: node.label,
|
||||
children: node.children
|
||||
}
|
||||
},
|
||||
/** 排序回调函数 */
|
||||
handleSortChang(column, prop, order) {
|
||||
prop = column.prop
|
||||
order = column.order
|
||||
if (this.order !== '' && this.order !== prop + 'Order') {
|
||||
this.queryParams[this.order] = undefined
|
||||
}
|
||||
if (order === 'descending') {
|
||||
this.queryParams[prop + 'Order'] = 'desc'
|
||||
this.order = prop + 'Order'
|
||||
} else if (order === 'ascending') {
|
||||
this.queryParams[prop + 'Order'] = 'asc'
|
||||
this.order = prop + 'Order'
|
||||
} else {
|
||||
this.queryParams[prop + 'Order'] = undefined
|
||||
}
|
||||
this.getList()
|
||||
},
|
||||
// 用户状态修改
|
||||
handleStatusChange(row) {
|
||||
const text = row.status === '2' ? '启用' : '停用'
|
||||
this.$confirm('确认要"' + text + '""' + row.username + '"用户吗?', '警告', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(function() {
|
||||
return changeUserStatus(row)
|
||||
}).then(() => {
|
||||
this.msgSuccess(text + '成功')
|
||||
}).catch(function() {
|
||||
row.status = row.status === '2' ? '1' : '2'
|
||||
})
|
||||
},
|
||||
// 取消按钮
|
||||
cancel() {
|
||||
this.open = false
|
||||
this.reset()
|
||||
},
|
||||
// 表单重置
|
||||
reset() {
|
||||
this.form = {
|
||||
userId: undefined,
|
||||
deptId: undefined,
|
||||
username: undefined,
|
||||
nickName: undefined,
|
||||
password: undefined,
|
||||
phone: undefined,
|
||||
email: undefined,
|
||||
sex: undefined,
|
||||
status: '2',
|
||||
remark: undefined,
|
||||
postIds: undefined,
|
||||
roleIds: undefined
|
||||
}
|
||||
this.resetForm('form')
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
this.queryParams.page = 1
|
||||
this.getList()
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.dateRange = []
|
||||
this.resetForm('queryForm')
|
||||
this.queryParams.deptId = ''
|
||||
this.handleQuery()
|
||||
},
|
||||
// 多选框选中数据
|
||||
handleSelectionChange(selection) {
|
||||
this.ids = selection.map(item => item.userId)
|
||||
this.single = selection.length !== 1
|
||||
this.multiple = !selection.length
|
||||
},
|
||||
/** 新增按钮操作 */
|
||||
handleAdd() {
|
||||
this.reset()
|
||||
this.getTreeselect()
|
||||
|
||||
listPost({ pageSize: 1000 }).then(response => {
|
||||
this.postOptions = response.data.list
|
||||
})
|
||||
listRole({ pageSize: 1000 }).then(response => {
|
||||
this.roleOptions = response.data.list
|
||||
})
|
||||
this.open = true
|
||||
this.title = '添加用户'
|
||||
this.form.password = this.initPassword
|
||||
},
|
||||
/** 修改按钮操作 */
|
||||
handleUpdate(row) {
|
||||
this.reset()
|
||||
|
||||
const userId = row.userId || this.ids
|
||||
getUser(userId).then(response => {
|
||||
this.form = response.data
|
||||
this.open = true
|
||||
this.title = '修改用户'
|
||||
this.form.password = ''
|
||||
})
|
||||
listPost({ pageSize: 1000 }).then(response => {
|
||||
this.postOptions = response.data.list
|
||||
})
|
||||
listRole({ pageSize: 1000 }).then(response => {
|
||||
this.roleOptions = response.data.list
|
||||
})
|
||||
},
|
||||
/** 重置密码按钮操作 */
|
||||
handleResetPwd(row) {
|
||||
this.$prompt('请输入"' + row.username + '"的新密码', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消'
|
||||
}).then(({ value }) => {
|
||||
resetUserPwd(row.userId, value).then(response => {
|
||||
if (response.code === 200) {
|
||||
this.msgSuccess(response.msg)
|
||||
} else {
|
||||
this.msgError(response.msg)
|
||||
}
|
||||
})
|
||||
}).catch(() => {})
|
||||
},
|
||||
/** 提交按钮 */
|
||||
submitForm: function() {
|
||||
this.$refs['form'].validate(valid => {
|
||||
if (valid) {
|
||||
if (this.form.userId !== undefined) {
|
||||
updateUser(this.form).then(response => {
|
||||
if (response.code === 200) {
|
||||
this.msgSuccess(response.msg)
|
||||
this.open = false
|
||||
this.getList()
|
||||
} else {
|
||||
this.msgError(response.msg)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
addUser(this.form).then(response => {
|
||||
if (response.code === 200) {
|
||||
this.msgSuccess(response.msg)
|
||||
this.open = false
|
||||
this.getList()
|
||||
} else {
|
||||
this.msgError(response.msg)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
/** 删除按钮操作 */
|
||||
handleDelete(row) {
|
||||
const Ids = (row.userId && [row.userId]) || this.ids
|
||||
this.$confirm('是否确认删除用户编号为"' + Ids + '"的数据项?', '警告', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(function() {
|
||||
return delUser({ 'ids': Ids })
|
||||
}).then((response) => {
|
||||
if (response.code === 200) {
|
||||
this.msgSuccess(response.msg)
|
||||
this.open = false
|
||||
this.getList()
|
||||
} else {
|
||||
this.msgError(response.msg)
|
||||
}
|
||||
}).catch(function() {})
|
||||
},
|
||||
/** 导出按钮操作 */
|
||||
handleExport() {
|
||||
const queryParams = this.queryParams
|
||||
this.$confirm('是否确认导出所有用户数据项?', '警告', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(function() {
|
||||
return exportUser(queryParams)
|
||||
}).then(response => {
|
||||
this.download(response.msg)
|
||||
}).catch(function() {})
|
||||
},
|
||||
/** 导入按钮操作 */
|
||||
handleImport() {
|
||||
this.upload.title = '用户导入'
|
||||
this.upload.open = true
|
||||
},
|
||||
/** 下载模板操作 */
|
||||
importTemplate() {
|
||||
importTemplate().then(response => {
|
||||
this.download(response.msg)
|
||||
})
|
||||
},
|
||||
// 文件上传中处理
|
||||
handleFileUploadProgress(event, file, fileList) {
|
||||
this.upload.isUploading = true
|
||||
},
|
||||
// 文件上传成功处理
|
||||
handleFileSuccess(response, file, fileList) {
|
||||
this.upload.open = false
|
||||
this.upload.isUploading = false
|
||||
this.$refs.upload.clearFiles()
|
||||
this.$alert(response.msg, '导入结果', { dangerouslyUseHTMLString: true })
|
||||
this.getList()
|
||||
},
|
||||
// 提交上传文件
|
||||
submitFileForm() {
|
||||
this.$refs.upload.submit()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
Reference in New Issue
Block a user