feat: 使用prettierrc对代码进行格式化

This commit is contained in:
piexlMax(奇淼
2024-11-09 10:32:26 +08:00
parent 87a4ce17e1
commit 7d9af64f6d
139 changed files with 12677 additions and 12656 deletions
File diff suppressed because it is too large Load Diff
+290 -326
View File
@@ -3,88 +3,74 @@
<warning-bar title="注:右上角头像下拉可切换角色" />
<div class="gva-table-box">
<div class="gva-btn-list">
<el-button
type="primary"
icon="plus"
@click="addAuthority(0)"
>新增角色</el-button>
<el-button type="primary" icon="plus" @click="addAuthority(0)"
>新增角色</el-button
>
</div>
<el-table
:data="tableData"
:tree-props="{children: 'children', hasChildren: 'hasChildren'}"
:tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
row-key="authorityId"
style="width: 100%"
>
<el-table-column
label="角色ID"
min-width="180"
prop="authorityId"
/>
<el-table-column label="角色ID" min-width="180" prop="authorityId" />
<el-table-column
align="left"
label="角色名称"
min-width="180"
prop="authorityName"
/>
<el-table-column
align="left"
label="操作"
width="460"
>
<el-table-column align="left" label="操作" width="460">
<template #default="scope">
<el-button
icon="setting"
type="primary"
link
@click="openDrawer(scope.row)"
>设置权限</el-button>
>设置权限</el-button
>
<el-button
icon="plus"
type="primary"
link
@click="addAuthority(scope.row.authorityId)"
>新增子角色</el-button>
>新增子角色</el-button
>
<el-button
icon="copy-document"
type="primary"
link
@click="copyAuthorityFunc(scope.row)"
>拷贝</el-button>
>拷贝</el-button
>
<el-button
icon="edit"
type="primary"
link
@click="editAuthority(scope.row)"
>编辑</el-button>
>编辑</el-button
>
<el-button
icon="delete"
type="primary"
link
@click="deleteAuth(scope.row)"
>删除</el-button>
>删除</el-button
>
</template>
</el-table-column>
</el-table>
</div>
<!-- 新增角色弹窗 -->
<el-drawer
v-model="authorityFormVisible"
:show-close="false"
>
<el-drawer v-model="authorityFormVisible" :show-close="false">
<template #header>
<div class="flex justify-between items-center">
<span class="text-lg">{{ authorityTitleForm }}</span>
<div>
<el-button @click="closeAuthorityForm">取 消</el-button>
<el-button
type="primary"
@click="submitAuthorityForm"
>确 定</el-button>
<el-button type="primary" @click="submitAuthorityForm"
>确 定</el-button
>
</div>
</div>
</template>
@@ -94,39 +80,33 @@
:rules="rules"
label-width="80px"
>
<el-form-item
label="父级角色"
prop="parentId"
>
<el-form-item label="父级角色" prop="parentId">
<el-cascader
v-model="form.parentId"
style="width:100%"
:disabled="dialogType==='add'"
style="width: 100%"
:disabled="dialogType === 'add'"
:options="AuthorityOption"
:props="{ checkStrictly: true,label:'authorityName',value:'authorityId',disabled:'disabled',emitPath:false}"
:props="{
checkStrictly: true,
label: 'authorityName',
value: 'authorityId',
disabled: 'disabled',
emitPath: false
}"
:show-all-levels="false"
filterable
/>
</el-form-item>
<el-form-item
label="角色ID"
prop="authorityId"
>
<el-form-item label="角色ID" prop="authorityId">
<el-input
v-model="form.authorityId"
:disabled="dialogType==='edit'"
:disabled="dialogType === 'edit'"
autocomplete="off"
maxlength="15"
/>
</el-form-item>
<el-form-item
label="角色姓名"
prop="authorityName"
>
<el-input
v-model="form.authorityName"
autocomplete="off"
/>
<el-form-item label="角色姓名" prop="authorityName">
<el-input v-model="form.authorityName" autocomplete="off" />
</el-form-item>
</el-form>
</el-drawer>
@@ -138,23 +118,12 @@
size="40%"
title="角色配置"
>
<el-tabs
:before-leave="autoEnter"
type="border-card"
>
<el-tabs :before-leave="autoEnter" type="border-card">
<el-tab-pane label="角色菜单">
<Menus
ref="menus"
:row="activeRow"
@changeRow="changeRow"
/>
<Menus ref="menus" :row="activeRow" @changeRow="changeRow" />
</el-tab-pane>
<el-tab-pane label="角色api">
<Apis
ref="apis"
:row="activeRow"
@changeRow="changeRow"
/>
<Apis ref="apis" :row="activeRow" @changeRow="changeRow" />
</el-tab-pane>
<el-tab-pane label="资源权限">
<Datas
@@ -170,288 +139,283 @@
</template>
<script setup>
import {
getAuthorityList,
deleteAuthority,
createAuthority,
updateAuthority,
copyAuthority
} from '@/api/authority'
import {
getAuthorityList,
deleteAuthority,
createAuthority,
updateAuthority,
copyAuthority
} from '@/api/authority'
import Menus from '@/view/superAdmin/authority/components/menus.vue'
import Apis from '@/view/superAdmin/authority/components/apis.vue'
import Datas from '@/view/superAdmin/authority/components/datas.vue'
import WarningBar from '@/components/warningBar/warningBar.vue'
import Menus from '@/view/superAdmin/authority/components/menus.vue'
import Apis from '@/view/superAdmin/authority/components/apis.vue'
import Datas from '@/view/superAdmin/authority/components/datas.vue'
import WarningBar from '@/components/warningBar/warningBar.vue'
import { ref } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { ref } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
defineOptions({
name: 'Authority'
})
const mustUint = (rule, value, callback) => {
if (!/^[0-9]*[1-9][0-9]*$/.test(value)) {
return callback(new Error('请输入正整数'))
}
return callback()
}
const AuthorityOption = ref([
{
authorityId: 0,
authorityName: '根角色/严格模式下为当前角色'
}
])
const drawer = ref(false)
const dialogType = ref('add')
const activeRow = ref({})
const authorityTitleForm = ref('新增角色')
const authorityFormVisible = ref(false)
const apiDialogFlag = ref(false)
const copyForm = ref({})
const form = ref({
authorityId: 0,
authorityName: '',
parentId: 0
})
const rules = ref({
authorityId: [
{ required: true, message: '请输入角色ID', trigger: 'blur' },
{ validator: mustUint, trigger: 'blur', message: '必须为正整数' }
],
authorityName: [
{ required: true, message: '请输入角色名', trigger: 'blur' }
],
parentId: [
{ required: true, message: '请选择父角色', trigger: 'blur' },
]
})
const tableData = ref([])
// 查询
const getTableData = async() => {
const table = await getAuthorityList()
if (table.code === 0) {
tableData.value = table.data
}
}
getTableData()
const changeRow = (key, value) => {
activeRow.value[key] = value
}
const menus = ref(null)
const apis = ref(null)
const datas = ref(null)
const autoEnter = (activeName, oldActiveName) => {
const paneArr = [menus, apis, datas]
if (oldActiveName) {
if (paneArr[oldActiveName].value.needConfirm) {
paneArr[oldActiveName].value.enterAndNext()
paneArr[oldActiveName].value.needConfirm = false
}
}
}
// 拷贝角色
const copyAuthorityFunc = (row) => {
setOptions()
authorityTitleForm.value = '拷贝角色'
dialogType.value = 'copy'
for (const k in form.value) {
form.value[k] = row[k]
}
copyForm.value = row
authorityFormVisible.value = true
}
const openDrawer = (row) => {
drawer.value = true
activeRow.value = row
}
// 删除角色
const deleteAuth = (row) => {
ElMessageBox.confirm('此操作将永久删除该角色, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
defineOptions({
name: 'Authority'
})
.then(async() => {
const res = await deleteAuthority({ authorityId: row.authorityId })
if (res.code === 0) {
ElMessage({
type: 'success',
message: '删除成功!'
})
getTableData()
}
})
.catch(() => {
ElMessage({
type: 'info',
message: '已取消删除'
})
})
}
// 初始化表单
const authorityForm = ref(null)
const initForm = () => {
if (authorityForm.value) {
authorityForm.value.resetFields()
const mustUint = (rule, value, callback) => {
if (!/^[0-9]*[1-9][0-9]*$/.test(value)) {
return callback(new Error('请输入正整数'))
}
return callback()
}
form.value = {
const AuthorityOption = ref([
{
authorityId: 0,
authorityName: '根角色/严格模式下为当前角色'
}
])
const drawer = ref(false)
const dialogType = ref('add')
const activeRow = ref({})
const authorityTitleForm = ref('新增角色')
const authorityFormVisible = ref(false)
const apiDialogFlag = ref(false)
const copyForm = ref({})
const form = ref({
authorityId: 0,
authorityName: '',
parentId: 0
}
}
// 关闭窗口
const closeAuthorityForm = () => {
initForm()
authorityFormVisible.value = false
apiDialogFlag.value = false
}
// 确定弹窗
})
const rules = ref({
authorityId: [
{ required: true, message: '请输入角色ID', trigger: 'blur' },
{ validator: mustUint, trigger: 'blur', message: '必须为正整数' }
],
authorityName: [
{ required: true, message: '请输入角色名', trigger: 'blur' }
],
parentId: [{ required: true, message: '请选择父角色', trigger: 'blur' }]
})
const submitAuthorityForm = () => {
authorityForm.value.validate(async valid => {
if (valid) {
form.value.authorityId = Number(form.value.authorityId)
switch (dialogType.value) {
case 'add':
{
const res = await createAuthority(form.value)
const tableData = ref([])
// 查询
const getTableData = async () => {
const table = await getAuthorityList()
if (table.code === 0) {
tableData.value = table.data
}
}
getTableData()
const changeRow = (key, value) => {
activeRow.value[key] = value
}
const menus = ref(null)
const apis = ref(null)
const datas = ref(null)
const autoEnter = (activeName, oldActiveName) => {
const paneArr = [menus, apis, datas]
if (oldActiveName) {
if (paneArr[oldActiveName].value.needConfirm) {
paneArr[oldActiveName].value.enterAndNext()
paneArr[oldActiveName].value.needConfirm = false
}
}
}
// 拷贝角色
const copyAuthorityFunc = (row) => {
setOptions()
authorityTitleForm.value = '拷贝角色'
dialogType.value = 'copy'
for (const k in form.value) {
form.value[k] = row[k]
}
copyForm.value = row
authorityFormVisible.value = true
}
const openDrawer = (row) => {
drawer.value = true
activeRow.value = row
}
// 删除角色
const deleteAuth = (row) => {
ElMessageBox.confirm('此操作将永久删除该角色, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
.then(async () => {
const res = await deleteAuthority({ authorityId: row.authorityId })
if (res.code === 0) {
ElMessage({
type: 'success',
message: '删除成功!'
})
getTableData()
}
})
.catch(() => {
ElMessage({
type: 'info',
message: '已取消删除'
})
})
}
// 初始化表单
const authorityForm = ref(null)
const initForm = () => {
if (authorityForm.value) {
authorityForm.value.resetFields()
}
form.value = {
authorityId: 0,
authorityName: '',
parentId: 0
}
}
// 关闭窗口
const closeAuthorityForm = () => {
initForm()
authorityFormVisible.value = false
apiDialogFlag.value = false
}
// 确定弹窗
const submitAuthorityForm = () => {
authorityForm.value.validate(async (valid) => {
if (valid) {
form.value.authorityId = Number(form.value.authorityId)
switch (dialogType.value) {
case 'add':
{
const res = await createAuthority(form.value)
if (res.code === 0) {
ElMessage({
type: 'success',
message: '添加成功!'
})
getTableData()
closeAuthorityForm()
}
}
break
case 'edit':
{
const res = await updateAuthority(form.value)
if (res.code === 0) {
ElMessage({
type: 'success',
message: '添加成功!'
})
getTableData()
closeAuthorityForm()
}
}
break
case 'copy': {
const data = {
authority: {
authorityId: 0,
authorityName: '',
datauthorityId: [],
parentId: 0
},
oldAuthorityId: 0
}
data.authority.authorityId = form.value.authorityId
data.authority.authorityName = form.value.authorityName
data.authority.parentId = form.value.parentId
data.authority.dataAuthorityId = copyForm.value.dataAuthorityId
data.oldAuthorityId = copyForm.value.authorityId
const res = await copyAuthority(data)
if (res.code === 0) {
ElMessage({
type: 'success',
message: '添加成功!'
message: '复制成功!'
})
getTableData()
closeAuthorityForm()
}
}
break
case 'edit':
{
const res = await updateAuthority(form.value)
if (res.code === 0) {
ElMessage({
type: 'success',
message: '添加成功!'
})
getTableData()
closeAuthorityForm()
}
}
break
case 'copy': {
const data = {
authority: {
authorityId: 0,
authorityName: '',
datauthorityId: [],
parentId: 0
},
oldAuthorityId: 0
}
data.authority.authorityId = form.value.authorityId
data.authority.authorityName = form.value.authorityName
data.authority.parentId = form.value.parentId
data.authority.dataAuthorityId = copyForm.value.dataAuthorityId
data.oldAuthorityId = copyForm.value.authorityId
const res = await copyAuthority(data)
if (res.code === 0) {
ElMessage({
type: 'success',
message: '复制成功!'
})
getTableData()
}
}
initForm()
authorityFormVisible.value = false
}
initForm()
authorityFormVisible.value = false
})
}
const setOptions = () => {
AuthorityOption.value = [
{
authorityId: 0,
authorityName: '根角色(严格模式下为当前用户角色)'
}
]
setAuthorityOptions(tableData.value, AuthorityOption.value, false)
}
const setAuthorityOptions = (AuthorityData, optionsData, disabled) => {
AuthorityData &&
AuthorityData.forEach((item) => {
if (item.children && item.children.length) {
const option = {
authorityId: item.authorityId,
authorityName: item.authorityName,
disabled: disabled || item.authorityId === form.value.authorityId,
children: []
}
setAuthorityOptions(
item.children,
option.children,
disabled || item.authorityId === form.value.authorityId
)
optionsData.push(option)
} else {
const option = {
authorityId: item.authorityId,
authorityName: item.authorityName,
disabled: disabled || item.authorityId === form.value.authorityId
}
optionsData.push(option)
}
})
}
// 增加角色
const addAuthority = (parentId) => {
initForm()
authorityTitleForm.value = '新增角色'
dialogType.value = 'add'
form.value.parentId = parentId
setOptions()
authorityFormVisible.value = true
}
// 编辑角色
const editAuthority = (row) => {
setOptions()
authorityTitleForm.value = '编辑角色'
dialogType.value = 'edit'
for (const key in form.value) {
form.value[key] = row[key]
}
})
}
const setOptions = () => {
AuthorityOption.value = [
{
authorityId: 0,
authorityName: '根角色(严格模式下为当前用户角色)'
}
]
setAuthorityOptions(tableData.value, AuthorityOption.value, false)
}
const setAuthorityOptions = (AuthorityData, optionsData, disabled) => {
AuthorityData &&
AuthorityData.forEach(item => {
if (item.children && item.children.length) {
const option = {
authorityId: item.authorityId,
authorityName: item.authorityName,
disabled: disabled || item.authorityId === form.value.authorityId,
children: []
}
setAuthorityOptions(
item.children,
option.children,
disabled || item.authorityId === form.value.authorityId
)
optionsData.push(option)
} else {
const option = {
authorityId: item.authorityId,
authorityName: item.authorityName,
disabled: disabled || item.authorityId === form.value.authorityId
}
optionsData.push(option)
}
})
}
// 增加角色
const addAuthority = (parentId) => {
initForm()
authorityTitleForm.value = '新增角色'
dialogType.value = 'add'
form.value.parentId = parentId
setOptions()
authorityFormVisible.value = true
}
// 编辑角色
const editAuthority = (row) => {
setOptions()
authorityTitleForm.value = '编辑角色'
dialogType.value = 'edit'
for (const key in form.value) {
form.value[key] = row[key]
setOptions()
authorityForm.value && authorityForm.value.clearValidate()
authorityFormVisible.value = true
}
setOptions()
authorityForm.value && authorityForm.value.clearValidate()
authorityFormVisible.value = true
}
</script>
<style lang="scss">
.authority {
.el-input-number {
margin-left: 15px;
span {
display: none;
.authority {
.el-input-number {
margin-left: 15px;
span {
display: none;
}
}
}
}
.tree-content{
margin-top: 10px;
height: calc(100vh - 158px);
overflow: auto;
}
.tree-content {
margin-top: 10px;
height: calc(100vh - 158px);
overflow: auto;
}
</style>
@@ -2,42 +2,41 @@
<div>
<div class="sticky top-0.5 z-10 flex space-x-2">
<el-input
v-model="filterTextName"
class="flex-1"
placeholder="筛选名字"
v-model="filterTextName"
class="flex-1"
placeholder="筛选名字"
/>
<el-input
v-model="filterTextPath"
class="flex-1"
placeholder="筛选路径"
v-model="filterTextPath"
class="flex-1"
placeholder="筛选路径"
/>
<el-button
class="float-right"
type="primary"
@click="authApiEnter"
>确 定</el-button>
<el-button class="float-right" type="primary" @click="authApiEnter"
>确 定</el-button
>
</div>
<div class="tree-content">
<el-scrollbar>
<el-tree
ref="apiTree"
:data="apiTreeData"
:default-checked-keys="apiTreeIds"
:props="apiDefaultProps"
default-expand-all
highlight-current
node-key="onlyId"
show-checkbox
:filter-node-method="filterNode"
@check="nodeChange"
ref="apiTree"
:data="apiTreeData"
:default-checked-keys="apiTreeIds"
:props="apiDefaultProps"
default-expand-all
highlight-current
node-key="onlyId"
show-checkbox
:filter-node-method="filterNode"
@check="nodeChange"
>
<template #default="{ _, data }">
<div class="flex items-center justify-between w-full pr-1">
<span>{{ data.description }} </span>
<el-tooltip
:content="data.path"
>
<span class="max-w-[240px] break-all overflow-ellipsis overflow-hidden">{{data.path}}</span>
<el-tooltip :content="data.path">
<span
class="max-w-[240px] break-all overflow-ellipsis overflow-hidden"
>{{ data.path }}</span
>
</el-tooltip>
</div>
</template>
@@ -48,126 +47,128 @@
</template>
<script setup>
import { getAllApis } from '@/api/api'
import { UpdateCasbin, getPolicyPathByAuthorityId } from '@/api/casbin'
import { ref, watch } from 'vue'
import { ElMessage } from 'element-plus'
import { getAllApis } from '@/api/api'
import { UpdateCasbin, getPolicyPathByAuthorityId } from '@/api/casbin'
import { ref, watch } from 'vue'
import { ElMessage } from 'element-plus'
defineOptions({
name: 'Apis',
})
const props = defineProps({
row: {
default: function() {
return {}
},
type: Object
}
})
const apiDefaultProps = ref({
children: 'children',
label: 'description'
})
const filterTextName = ref('')
const filterTextPath = ref('')
const apiTreeData = ref([])
const apiTreeIds = ref([])
const activeUserId = ref('')
const init = async() => {
const res2 = await getAllApis()
const apis = res2.data.apis
apiTreeData.value = buildApiTree(apis)
const res = await getPolicyPathByAuthorityId({
authorityId: props.row.authorityId
defineOptions({
name: 'Apis'
})
activeUserId.value = props.row.authorityId
apiTreeIds.value = []
res.data.paths && res.data.paths.forEach(item => {
apiTreeIds.value.push('p:' + item.path + 'm:' + item.method)
})
}
init()
const needConfirm = ref(false)
const nodeChange = () => {
needConfirm.value = true
}
// 暴露给外层使用的切换拦截统一方法
const enterAndNext = () => {
authApiEnter()
}
// 创建api树方法
const buildApiTree = (apis) => {
const apiObj = {}
apis &&
apis.forEach(item => {
item.onlyId = 'p:' + item.path + 'm:' + item.method
if (Object.prototype.hasOwnProperty.call(apiObj, item.apiGroup)) {
apiObj[item.apiGroup].push(item)
} else {
Object.assign(apiObj, { [item.apiGroup]: [item] })
}
})
const apiTree = []
for (const key in apiObj) {
const treeNode = {
ID: key,
description: key + '组',
children: apiObj[key]
const props = defineProps({
row: {
default: function () {
return {}
},
type: Object
}
apiTree.push(treeNode)
}
return apiTree
}
})
// 关联关系确定
const apiTree = ref(null)
const authApiEnter = async() => {
const checkArr = apiTree.value.getCheckedNodes(true)
var casbinInfos = []
checkArr && checkArr.forEach(item => {
var casbinInfo = {
path: item.path,
method: item.method
const apiDefaultProps = ref({
children: 'children',
label: 'description'
})
const filterTextName = ref('')
const filterTextPath = ref('')
const apiTreeData = ref([])
const apiTreeIds = ref([])
const activeUserId = ref('')
const init = async () => {
const res2 = await getAllApis()
const apis = res2.data.apis
apiTreeData.value = buildApiTree(apis)
const res = await getPolicyPathByAuthorityId({
authorityId: props.row.authorityId
})
activeUserId.value = props.row.authorityId
apiTreeIds.value = []
res.data.paths &&
res.data.paths.forEach((item) => {
apiTreeIds.value.push('p:' + item.path + 'm:' + item.method)
})
}
init()
const needConfirm = ref(false)
const nodeChange = () => {
needConfirm.value = true
}
// 暴露给外层使用的切换拦截统一方法
const enterAndNext = () => {
authApiEnter()
}
// 创建api树方法
const buildApiTree = (apis) => {
const apiObj = {}
apis &&
apis.forEach((item) => {
item.onlyId = 'p:' + item.path + 'm:' + item.method
if (Object.prototype.hasOwnProperty.call(apiObj, item.apiGroup)) {
apiObj[item.apiGroup].push(item)
} else {
Object.assign(apiObj, { [item.apiGroup]: [item] })
}
})
const apiTree = []
for (const key in apiObj) {
const treeNode = {
ID: key,
description: key + '组',
children: apiObj[key]
}
apiTree.push(treeNode)
}
casbinInfos.push(casbinInfo)
return apiTree
}
// 关联关系确定
const apiTree = ref(null)
const authApiEnter = async () => {
const checkArr = apiTree.value.getCheckedNodes(true)
var casbinInfos = []
checkArr &&
checkArr.forEach((item) => {
var casbinInfo = {
path: item.path,
method: item.method
}
casbinInfos.push(casbinInfo)
})
const res = await UpdateCasbin({
authorityId: activeUserId.value,
casbinInfos
})
if (res.code === 0) {
ElMessage({ type: 'success', message: 'api设置成功' })
}
}
defineExpose({
needConfirm,
enterAndNext
})
const res = await UpdateCasbin({
authorityId: activeUserId.value,
casbinInfos
const filterNode = (value, data) => {
if (!filterTextName.value && !filterTextPath.value) return true
let matchesName, matchesPath
if (!filterTextName.value) {
matchesName = true
} else {
matchesName =
data.description && data.description.includes(filterTextName.value)
}
if (!filterTextPath.value) {
matchesPath = true
} else {
matchesPath = data.path && data.path.includes(filterTextPath.value)
}
return matchesName && matchesPath
}
watch([filterTextName, filterTextPath], () => {
apiTree.value.filter('')
})
if (res.code === 0) {
ElMessage({ type: 'success', message: 'api设置成功' })
}
}
defineExpose({
needConfirm,
enterAndNext
})
const filterNode = (value, data) => {
if (!filterTextName.value && !filterTextPath.value) return true
let matchesName,matchesPath;
if (!filterTextName.value){
matchesName = true
}else {
matchesName = data.description && data.description.includes(filterTextName.value)
}
if (!filterTextPath.value){
matchesPath = true
}else {
matchesPath = data.path && data.path.includes(filterTextPath.value)
}
return matchesName && matchesPath
}
watch([filterTextName, filterTextPath], () => {
apiTree.value.filter('')
})
</script>
@@ -5,140 +5,141 @@
href="https://plugin.gin-vue-admin.com/#/layout/newPluginInfo?id=36"
/>
<div class="sticky top-0.5 z-10 my-4">
<el-button
class="float-left"
type="primary"
@click="all"
>全选</el-button>
<el-button
class="float-left"
type="primary"
@click="self"
>本角色</el-button>
<el-button
class="float-left"
type="primary"
@click="selfAndChildren"
>本角色及子角色</el-button>
<el-button
class="float-right"
type="primary"
@click="authDataEnter"
>确 定</el-button>
<el-button class="float-left" type="primary" @click="all">全选</el-button>
<el-button class="float-left" type="primary" @click="self"
>本角色</el-button
>
<el-button class="float-left" type="primary" @click="selfAndChildren"
>本角色及子角色</el-button
>
<el-button class="float-right" type="primary" @click="authDataEnter"
>确 定</el-button
>
</div>
<div class="clear-both pt-4">
<el-checkbox-group
v-model="dataAuthorityId"
@change="selectAuthority"
>
<el-checkbox-group v-model="dataAuthorityId" @change="selectAuthority">
<el-checkbox
v-for="(item,key) in authoritys"
v-for="(item, key) in authoritys"
:key="key"
:label="item"
>{{ item.authorityName }}</el-checkbox>
>{{ item.authorityName }}</el-checkbox
>
</el-checkbox-group>
</div>
</div>
</template>
<script setup>
import { setDataAuthority } from '@/api/authority'
import WarningBar from '@/components/warningBar/warningBar.vue'
import { ref } from 'vue'
import { ElMessage } from 'element-plus'
import { setDataAuthority } from '@/api/authority'
import WarningBar from '@/components/warningBar/warningBar.vue'
import { ref } from 'vue'
import { ElMessage } from 'element-plus'
defineOptions({
name: 'Datas'
})
defineOptions({
name: 'Datas'
})
const props = defineProps({
row: {
default: function() {
return {}
const props = defineProps({
row: {
default: function () {
return {}
},
type: Object
},
type: Object
},
authority: {
default: function() {
return []
},
type: Array
}
})
const authoritys = ref([])
const needConfirm = ref(false)
// 平铺角色
const roundAuthority = (authoritysData) => {
authoritysData && authoritysData.forEach(item => {
const obj = {}
obj.authorityId = item.authorityId
obj.authorityName = item.authorityName
authoritys.value.push(obj)
if (item.children && item.children.length) {
roundAuthority(item.children)
authority: {
default: function () {
return []
},
type: Array
}
})
}
const dataAuthorityId = ref([])
const init = () => {
roundAuthority(props.authority)
props.row.dataAuthorityId && props.row.dataAuthorityId.forEach(item => {
const obj = authoritys.value && authoritys.value.filter(au => au.authorityId === item.authorityId) && authoritys.value.filter(au => au.authorityId === item.authorityId)[0]
dataAuthorityId.value.push(obj)
})
}
init()
// 暴露给外层使用的切换拦截统一方法
const enterAndNext = () => {
authDataEnter()
}
const emit = defineEmits(['changeRow'])
const all = () => {
dataAuthorityId.value = [...authoritys.value]
emit('changeRow', 'dataAuthorityId', dataAuthorityId.value)
needConfirm.value = true
}
const self = () => {
dataAuthorityId.value = authoritys.value.filter(item => item.authorityId === props.row.authorityId)
emit('changeRow', 'dataAuthorityId', dataAuthorityId.value)
needConfirm.value = true
}
const selfAndChildren = () => {
const arrBox = []
getChildrenId(props.row, arrBox)
dataAuthorityId.value = authoritys.value.filter(item => arrBox.indexOf(item.authorityId) > -1)
emit('changeRow', 'dataAuthorityId', dataAuthorityId.value)
needConfirm.value = true
}
const getChildrenId = (row, arrBox) => {
arrBox.push(row.authorityId)
row.children && row.children.forEach(item => {
getChildrenId(item, arrBox)
})
}
// 提交
const authDataEnter = async() => {
const res = await setDataAuthority(props.row)
if (res.code === 0) {
ElMessage({ type: 'success', message: '资源设置成功' })
const authoritys = ref([])
const needConfirm = ref(false)
// 平铺角色
const roundAuthority = (authoritysData) => {
authoritysData &&
authoritysData.forEach((item) => {
const obj = {}
obj.authorityId = item.authorityId
obj.authorityName = item.authorityName
authoritys.value.push(obj)
if (item.children && item.children.length) {
roundAuthority(item.children)
}
})
}
}
// 选择
const selectAuthority = () => {
dataAuthorityId.value = dataAuthorityId.value.filter(item => item)
emit('changeRow', 'dataAuthorityId', dataAuthorityId.value)
needConfirm.value = true
}
const dataAuthorityId = ref([])
const init = () => {
roundAuthority(props.authority)
props.row.dataAuthorityId &&
props.row.dataAuthorityId.forEach((item) => {
const obj =
authoritys.value &&
authoritys.value.filter(
(au) => au.authorityId === item.authorityId
) &&
authoritys.value.filter(
(au) => au.authorityId === item.authorityId
)[0]
dataAuthorityId.value.push(obj)
})
}
defineExpose({
enterAndNext,
needConfirm
})
init()
// 暴露给外层使用的切换拦截统一方法
const enterAndNext = () => {
authDataEnter()
}
const emit = defineEmits(['changeRow'])
const all = () => {
dataAuthorityId.value = [...authoritys.value]
emit('changeRow', 'dataAuthorityId', dataAuthorityId.value)
needConfirm.value = true
}
const self = () => {
dataAuthorityId.value = authoritys.value.filter(
(item) => item.authorityId === props.row.authorityId
)
emit('changeRow', 'dataAuthorityId', dataAuthorityId.value)
needConfirm.value = true
}
const selfAndChildren = () => {
const arrBox = []
getChildrenId(props.row, arrBox)
dataAuthorityId.value = authoritys.value.filter(
(item) => arrBox.indexOf(item.authorityId) > -1
)
emit('changeRow', 'dataAuthorityId', dataAuthorityId.value)
needConfirm.value = true
}
const getChildrenId = (row, arrBox) => {
arrBox.push(row.authorityId)
row.children &&
row.children.forEach((item) => {
getChildrenId(item, arrBox)
})
}
// 提交
const authDataEnter = async () => {
const res = await setDataAuthority(props.row)
if (res.code === 0) {
ElMessage({ type: 'success', message: '资源设置成功' })
}
}
// 选择
const selectAuthority = () => {
dataAuthorityId.value = dataAuthorityId.value.filter((item) => item)
emit('changeRow', 'dataAuthorityId', dataAuthorityId.value)
needConfirm.value = true
}
defineExpose({
enterAndNext,
needConfirm
})
</script>
@@ -1,16 +1,10 @@
<template>
<div>
<div class="sticky top-0.5 z-10">
<el-input
v-model="filterText"
class="w-3/5"
placeholder="筛选"
/>
<el-button
class="float-right"
type="primary"
@click="relation"
>确 定</el-button>
<el-input v-model="filterText" class="w-3/5" placeholder="筛选" />
<el-button class="float-right" type="primary" @click="relation"
>确 定</el-button
>
</div>
<div class="tree-content clear-both">
<el-scrollbar>
@@ -26,25 +20,24 @@
:filter-node-method="filterNode"
@check="nodeChange"
>
<template #default="{ node , data }">
<template #default="{ node, data }">
<span class="custom-tree-node">
<span>{{ node.label }}</span>
<span v-if="node.checked">
<el-button
type="primary"
link
:style="{color:row.defaultRouter === data.name?'#E6A23C':'#85ce61'}"
:style="{
color:
row.defaultRouter === data.name ? '#E6A23C' : '#85ce61'
}"
@click="() => setDefault(data)"
>
{{ row.defaultRouter === data.name?"首页":"设为首页" }}
{{ row.defaultRouter === data.name ? '首页' : '设为首页' }}
</el-button>
</span>
<span v-if="data.menuBtn.length">
<el-button
type="primary"
link
@click="() => OpenBtn(data)"
>
<el-button type="primary" link @click="() => OpenBtn(data)">
分配按钮
</el-button>
</span>
@@ -53,37 +46,21 @@
</el-tree>
</el-scrollbar>
</div>
<el-dialog
v-model="btnVisible"
title="分配按钮"
destroy-on-close
>
<el-dialog v-model="btnVisible" title="分配按钮" destroy-on-close>
<el-table
ref="btnTableRef"
:data="btnData"
row-key="ID"
@selection-change="handleSelectionChange"
>
<el-table-column
type="selection"
width="55"
/>
<el-table-column
label="按钮名称"
prop="name"
/>
<el-table-column
label="按钮备注"
prop="desc"
/>
<el-table-column type="selection" width="55" />
<el-table-column label="按钮名称" prop="name" />
<el-table-column label="按钮备注" prop="desc" />
</el-table>
<template #footer>
<div class="dialog-footer">
<el-button @click="closeDialog">取 消</el-button>
<el-button
type="primary"
@click="enterDialog"
>确 定</el-button>
<el-button type="primary" @click="enterDialog">确 定</el-button>
</div>
</template>
</el-dialog>
@@ -91,158 +68,166 @@
</template>
<script setup>
import { getBaseMenuTree, getMenuAuthority, addMenuAuthority } from '@/api/menu'
import {
updateAuthority
} from '@/api/authority'
import { getAuthorityBtnApi, setAuthorityBtnApi } from '@/api/authorityBtn'
import { nextTick, ref, watch } from 'vue'
import { ElMessage } from 'element-plus'
import {
getBaseMenuTree,
getMenuAuthority,
addMenuAuthority
} from '@/api/menu'
import { updateAuthority } from '@/api/authority'
import { getAuthorityBtnApi, setAuthorityBtnApi } from '@/api/authorityBtn'
import { nextTick, ref, watch } from 'vue'
import { ElMessage } from 'element-plus'
defineOptions({
name: 'Menus'
})
defineOptions({
name: 'Menus'
})
const props = defineProps({
row: {
default: function() {
return {}
},
type: Object
}
})
const emit = defineEmits(['changeRow'])
const filterText = ref('')
const menuTreeData = ref([])
const menuTreeIds = ref([])
const needConfirm = ref(false)
const menuDefaultProps = ref({
children: 'children',
label: function(data) {
return data.meta.title
},
disabled: function(data) {
return props.row.defaultRouter === data.name
}
})
const init = async() => {
// 获取所有菜单树
const res = await getBaseMenuTree()
menuTreeData.value = res.data.menus
const res1 = await getMenuAuthority({ authorityId: props.row.authorityId })
const menus = res1.data.menus
const arr = []
menus.forEach(item => {
// 防止直接选中父级造成全选
if (!menus.some(same => same.parentId === item.menuId)) {
arr.push(Number(item.menuId))
const props = defineProps({
row: {
default: function () {
return {}
},
type: Object
}
})
menuTreeIds.value = arr
}
init()
const setDefault = async(data) => {
const res = await updateAuthority({ authorityId: props.row.authorityId, AuthorityName: props.row.authorityName, parentId: props.row.parentId, defaultRouter: data.name })
if (res.code === 0) {
ElMessage({ type: 'success', message: '设置成功' })
emit('changeRow', 'defaultRouter', res.data.authority.defaultRouter)
}
}
const nodeChange = () => {
needConfirm.value = true
}
// 暴露给外层使用的切换拦截统一方法
const enterAndNext = () => {
relation()
}
// 关联树 确认方法
const menuTree = ref(null)
const relation = async() => {
const checkArr = menuTree.value.getCheckedNodes(false, true)
const res = await addMenuAuthority({
menus: checkArr,
authorityId: props.row.authorityId
const emit = defineEmits(['changeRow'])
const filterText = ref('')
const menuTreeData = ref([])
const menuTreeIds = ref([])
const needConfirm = ref(false)
const menuDefaultProps = ref({
children: 'children',
label: function (data) {
return data.meta.title
},
disabled: function (data) {
return props.row.defaultRouter === data.name
}
})
if (res.code === 0) {
ElMessage({
type: 'success',
message: '菜单设置成功!'
const init = async () => {
// 获取所有菜单树
const res = await getBaseMenuTree()
menuTreeData.value = res.data.menus
const res1 = await getMenuAuthority({ authorityId: props.row.authorityId })
const menus = res1.data.menus
const arr = []
menus.forEach((item) => {
// 防止直接选中父级造成全选
if (!menus.some((same) => same.parentId === item.menuId)) {
arr.push(Number(item.menuId))
}
})
menuTreeIds.value = arr
}
}
defineExpose({ enterAndNext, needConfirm })
init()
const btnVisible = ref(false)
const btnData = ref([])
const multipleSelection = ref([])
const btnTableRef = ref()
let menuID = ''
const OpenBtn = async(data) => {
menuID = data.ID
const res = await getAuthorityBtnApi({ menuID: menuID, authorityId: props.row.authorityId })
if (res.code === 0) {
openDialog(data)
await nextTick()
if (res.data.selected) {
res.data.selected.forEach(id => {
btnData.value.some(item => {
if (item.ID === id) {
btnTableRef.value.toggleRowSelection(item, true)
}
})
const setDefault = async (data) => {
const res = await updateAuthority({
authorityId: props.row.authorityId,
AuthorityName: props.row.authorityName,
parentId: props.row.parentId,
defaultRouter: data.name
})
if (res.code === 0) {
ElMessage({ type: 'success', message: '设置成功' })
emit('changeRow', 'defaultRouter', res.data.authority.defaultRouter)
}
}
const nodeChange = () => {
needConfirm.value = true
}
// 暴露给外层使用的切换拦截统一方法
const enterAndNext = () => {
relation()
}
// 关联树 确认方法
const menuTree = ref(null)
const relation = async () => {
const checkArr = menuTree.value.getCheckedNodes(false, true)
const res = await addMenuAuthority({
menus: checkArr,
authorityId: props.row.authorityId
})
if (res.code === 0) {
ElMessage({
type: 'success',
message: '菜单设置成功!'
})
}
}
}
const handleSelectionChange = (val) => {
multipleSelection.value = val
}
defineExpose({ enterAndNext, needConfirm })
const openDialog = (data) => {
btnVisible.value = true
btnData.value = data.menuBtn
}
const btnVisible = ref(false)
const closeDialog = () => {
btnVisible.value = false
}
const enterDialog = async() => {
const selected = multipleSelection.value.map(item => item.ID)
const res = await setAuthorityBtnApi({
menuID,
selected,
authorityId: props.row.authorityId
})
if (res.code === 0) {
ElMessage({ type: 'success', message: '设置成功' })
const btnData = ref([])
const multipleSelection = ref([])
const btnTableRef = ref()
let menuID = ''
const OpenBtn = async (data) => {
menuID = data.ID
const res = await getAuthorityBtnApi({
menuID: menuID,
authorityId: props.row.authorityId
})
if (res.code === 0) {
openDialog(data)
await nextTick()
if (res.data.selected) {
res.data.selected.forEach((id) => {
btnData.value.some((item) => {
if (item.ID === id) {
btnTableRef.value.toggleRowSelection(item, true)
}
})
})
}
}
}
const handleSelectionChange = (val) => {
multipleSelection.value = val
}
const openDialog = (data) => {
btnVisible.value = true
btnData.value = data.menuBtn
}
const closeDialog = () => {
btnVisible.value = false
}
}
const enterDialog = async () => {
const selected = multipleSelection.value.map((item) => item.ID)
const res = await setAuthorityBtnApi({
menuID,
selected,
authorityId: props.row.authorityId
})
if (res.code === 0) {
ElMessage({ type: 'success', message: '设置成功' })
btnVisible.value = false
}
}
const filterNode = (value, data) => {
if (!value) return true
// console.log(data.mate.title)
return data.meta.title.indexOf(value) !== -1
}
watch(filterText, (val) => {
menuTree.value.filter(val)
})
const filterNode = (value, data) => {
if (!value) return true
// console.log(data.mate.title)
return data.meta.title.indexOf(value) !== -1
}
watch(filterText, (val) => {
menuTree.value.filter(val)
})
</script>
<style lang="scss" scoped>
.custom-tree-node{
span+span{
@apply ml-3;
.custom-tree-node {
span + span {
@apply ml-3;
}
}
}
</style>
@@ -1,34 +1,49 @@
<template>
<div>
<warning-bar title="获取字典且缓存方法已在前端utils/dictionary 已经封装完成 不必自己书写 使用方法查看文件内注释" />
<warning-bar
title="获取字典且缓存方法已在前端utils/dictionary 已经封装完成 不必自己书写 使用方法查看文件内注释"
/>
<div class="flex gap-4 p-2">
<div class="flex-none w-52 bg-white text-slate-700 dark:text-slate-400 dark:bg-slate-900 rounded p-4">
<div
class="flex-none w-52 bg-white text-slate-700 dark:text-slate-400 dark:bg-slate-900 rounded p-4"
>
<div class="flex justify-between items-center">
<span class="text font-bold">字典列表</span>
<el-button type="primary" @click="openDrawer">
新增
</el-button>
<el-button type="primary" @click="openDrawer"> 新增 </el-button>
</div>
<el-scrollbar class="mt-4" style="height: calc(100vh - 300px)">
<div
v-for="dictionary in dictionaryData" :key="dictionary.ID"
v-for="dictionary in dictionaryData"
:key="dictionary.ID"
class="rounded flex justify-between items-center px-2 py-4 cursor-pointer mt-2 hover:bg-blue-50 dark:hover:bg-blue-900 bg-gray-50 dark:bg-gray-800 gap-4"
:class="selectID === dictionary.ID ? 'text-active' : 'text-slate-700 dark:text-slate-50'"
:class="
selectID === dictionary.ID
? 'text-active'
: 'text-slate-700 dark:text-slate-50'
"
@click="toDetail(dictionary)"
>
<span class="max-w-[160px] truncate">{{ dictionary.name }}</span>
<div class="min-w-[40px]">
<el-icon class="text-blue-500" @click.stop="updateSysDictionaryFunc(dictionary)">
<el-icon
class="text-blue-500"
@click.stop="updateSysDictionaryFunc(dictionary)"
>
<Edit />
</el-icon>
<el-icon class="ml-2 text-red-500" @click="deleteSysDictionaryFunc(dictionary)">
<el-icon
class="ml-2 text-red-500"
@click="deleteSysDictionaryFunc(dictionary)"
>
<Delete />
</el-icon>
</div>
</div>
</el-scrollbar>
</div>
<div class="flex-1 bg-white text-slate-700 dark:text-slate-400 dark:bg-slate-900">
<div
class="flex-1 bg-white text-slate-700 dark:text-slate-400 dark:bg-slate-900"
>
<sysDictionaryDetail :sys-dictionary-i-d="selectID" />
</div>
</div>
@@ -40,29 +55,51 @@
>
<template #header>
<div class="flex justify-between items-center">
<span class="text-lg">{{ type === 'create' ? '添加字典' : '修改字典' }}</span>
<span class="text-lg">{{
type === 'create' ? '添加字典' : '修改字典'
}}</span>
<div>
<el-button @click="closeDrawer">
取 消
</el-button>
<el-button type="primary" @click="enterDrawer">
确 定
</el-button>
<el-button @click="closeDrawer"> 取 消 </el-button>
<el-button type="primary" @click="enterDrawer"> 确 定 </el-button>
</div>
</div>
</template>
<el-form ref="drawerForm" :model="formData" :rules="rules" label-width="110px">
<el-form
ref="drawerForm"
:model="formData"
:rules="rules"
label-width="110px"
>
<el-form-item label="字典名(中)" prop="name">
<el-input v-model="formData.name" placeholder="请输入字典名(中)" clearable :style="{ width: '100%' }" />
<el-input
v-model="formData.name"
placeholder="请输入字典名(中)"
clearable
:style="{ width: '100%' }"
/>
</el-form-item>
<el-form-item label="字典名(英)" prop="type">
<el-input v-model="formData.type" placeholder="请输入字典名(英)" clearable :style="{ width: '100%' }" />
<el-input
v-model="formData.type"
placeholder="请输入字典名(英)"
clearable
:style="{ width: '100%' }"
/>
</el-form-item>
<el-form-item label="状态" prop="status" required>
<el-switch v-model="formData.status" active-text="开启" inactive-text="停用" />
<el-switch
v-model="formData.status"
active-text="开启"
inactive-text="停用"
/>
</el-form-item>
<el-form-item label="描述" prop="desc">
<el-input v-model="formData.desc" placeholder="请输入描述" clearable :style="{ width: '100%' }" />
<el-input
v-model="formData.desc"
placeholder="请输入描述"
clearable
:style="{ width: '100%' }"
/>
</el-form-item>
</el-form>
</el-drawer>
@@ -70,146 +107,146 @@
</template>
<script setup>
import {
createSysDictionary,
deleteSysDictionary,
updateSysDictionary,
findSysDictionary,
getSysDictionaryList,
} from '@/api/sysDictionary' // 此处请自行替换地址
import WarningBar from '@/components/warningBar/warningBar.vue'
import { ref } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import {
createSysDictionary,
deleteSysDictionary,
updateSysDictionary,
findSysDictionary,
getSysDictionaryList
} from '@/api/sysDictionary' // 此处请自行替换地址
import WarningBar from '@/components/warningBar/warningBar.vue'
import { ref } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import sysDictionaryDetail from './sysDictionaryDetail.vue'
import { Edit } from '@element-plus/icons-vue'
import sysDictionaryDetail from './sysDictionaryDetail.vue'
import { Edit } from '@element-plus/icons-vue'
defineOptions({
name: 'SysDictionary',
})
defineOptions({
name: 'SysDictionary'
})
const selectID = ref(0)
const selectID = ref(0)
const formData = ref({
name: null,
type: null,
status: true,
desc: null,
})
const rules = ref({
name: [
{
required: true,
message: '请输入字典名(中)',
trigger: 'blur',
},
],
type: [
{
required: true,
message: '请输入字典名(英)',
trigger: 'blur',
},
],
desc: [
{
required: true,
message: '请输入描述',
trigger: 'blur',
},
],
})
const dictionaryData = ref([])
// 查询
const getTableData = async () => {
const res = await getSysDictionaryList()
if (res.code === 0) {
dictionaryData.value = res.data
selectID.value = res.data[0].ID
}
}
getTableData()
const toDetail = (row) => {
selectID.value = row.ID
}
const drawerFormVisible = ref(false)
const type = ref('')
const updateSysDictionaryFunc = async (row) => {
const res = await findSysDictionary({ ID: row.ID, status: row.status })
type.value = 'update'
if (res.code === 0) {
formData.value = res.data.resysDictionary
drawerFormVisible.value = true
}
}
const closeDrawer = () => {
drawerFormVisible.value = false
formData.value = {
const formData = ref({
name: null,
type: null,
status: true,
desc: null,
}
}
const deleteSysDictionaryFunc = async (row) => {
ElMessageBox.confirm('确定要删除吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(async () => {
const res = await deleteSysDictionary({ ID: row.ID })
if (res.code === 0) {
ElMessage({
type: 'success',
message: '删除成功',
})
getTableData()
}
desc: null
})
const rules = ref({
name: [
{
required: true,
message: '请输入字典名(中)',
trigger: 'blur'
}
],
type: [
{
required: true,
message: '请输入字典名(英)',
trigger: 'blur'
}
],
desc: [
{
required: true,
message: '请输入描述',
trigger: 'blur'
}
]
})
}
const drawerForm = ref(null)
const enterDrawer = async () => {
drawerForm.value.validate(async (valid) => {
if (!valid) return
let res
switch (type.value) {
case 'create':
res = await createSysDictionary(formData.value)
break
case 'update':
res = await updateSysDictionary(formData.value)
break
default:
res = await createSysDictionary(formData.value)
break
}
const dictionaryData = ref([])
// 查询
const getTableData = async () => {
const res = await getSysDictionaryList()
if (res.code === 0) {
ElMessage.success('操作成功')
closeDrawer()
getTableData()
dictionaryData.value = res.data
selectID.value = res.data[0].ID
}
})
}
const openDrawer = () => {
type.value = 'create'
drawerForm.value && drawerForm.value.clearValidate()
drawerFormVisible.value = true
}
}
getTableData()
const toDetail = (row) => {
selectID.value = row.ID
}
const drawerFormVisible = ref(false)
const type = ref('')
const updateSysDictionaryFunc = async (row) => {
const res = await findSysDictionary({ ID: row.ID, status: row.status })
type.value = 'update'
if (res.code === 0) {
formData.value = res.data.resysDictionary
drawerFormVisible.value = true
}
}
const closeDrawer = () => {
drawerFormVisible.value = false
formData.value = {
name: null,
type: null,
status: true,
desc: null
}
}
const deleteSysDictionaryFunc = async (row) => {
ElMessageBox.confirm('确定要删除吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(async () => {
const res = await deleteSysDictionary({ ID: row.ID })
if (res.code === 0) {
ElMessage({
type: 'success',
message: '删除成功'
})
getTableData()
}
})
}
const drawerForm = ref(null)
const enterDrawer = async () => {
drawerForm.value.validate(async (valid) => {
if (!valid) return
let res
switch (type.value) {
case 'create':
res = await createSysDictionary(formData.value)
break
case 'update':
res = await updateSysDictionary(formData.value)
break
default:
res = await createSysDictionary(formData.value)
break
}
if (res.code === 0) {
ElMessage.success('操作成功')
closeDrawer()
getTableData()
}
})
}
const openDrawer = () => {
type.value = 'create'
drawerForm.value && drawerForm.value.clearValidate()
drawerFormVisible.value = true
}
</script>
<style>
.dict-box {
height: calc(100vh - 240px);
}
.dict-box {
height: calc(100vh - 240px);
}
.active {
background-color: var(--el-color-primary) !important;
color: #fff;
}
.active {
background-color: var(--el-color-primary) !important;
color: #fff;
}
</style>
@@ -3,11 +3,7 @@
<div class="gva-table-box">
<div class="gva-btn-list justify-between">
<span class="text font-bold">字典详细内容</span>
<el-button
type="primary"
icon="plus"
@click="openDrawer"
>
<el-button type="primary" icon="plus" @click="openDrawer">
新增字典项
</el-button>
</div>
@@ -18,37 +14,18 @@
tooltip-effect="dark"
row-key="ID"
>
<el-table-column
type="selection"
width="55"
/>
<el-table-column
align="left"
label="日期"
width="180"
>
<el-table-column type="selection" width="55" />
<el-table-column align="left" label="日期" width="180">
<template #default="scope">
{{ formatDate(scope.row.CreatedAt) }}
</template>
</el-table-column>
<el-table-column
align="left"
label="展示值"
prop="label"
/>
<el-table-column align="left" label="展示值" prop="label" />
<el-table-column
align="left"
label="字典值"
prop="value"
/>
<el-table-column align="left" label="字典值" prop="value" />
<el-table-column
align="left"
label="扩展值"
prop="extend"
/>
<el-table-column align="left" label="扩展值" prop="extend" />
<el-table-column
align="left"
@@ -68,11 +45,7 @@
width="120"
/>
<el-table-column
align="left"
label="操作"
width="180"
>
<el-table-column align="left" label="操作" width="180">
<template #default="scope">
<el-button
type="primary"
@@ -115,14 +88,12 @@
>
<template #header>
<div class="flex justify-between items-center">
<span class="text-lg">{{ type==='create' ? '添加字典项' : '修改字典项' }}</span>
<span class="text-lg">{{
type === 'create' ? '添加字典项' : '修改字典项'
}}</span>
<div>
<el-button @click="closeDrawer">
取 消
</el-button>
<el-button type="primary" @click="enterDrawer">
确 定
</el-button>
<el-button @click="closeDrawer"> 取 消 </el-button>
<el-button type="primary" @click="enterDrawer"> 确 定 </el-button>
</div>
</div>
</template>
@@ -132,54 +103,38 @@
:rules="rules"
label-width="110px"
>
<el-form-item
label="展示值"
prop="label"
>
<el-form-item label="展示值" prop="label">
<el-input
v-model="formData.label"
placeholder="请输入展示值"
clearable
:style="{width: '100%'}"
:style="{ width: '100%' }"
/>
</el-form-item>
<el-form-item
label="字典值"
prop="value"
>
<el-form-item label="字典值" prop="value">
<el-input
v-model="formData.value"
placeholder="请输入字典值"
clearable
:style="{width: '100%'}"
:style="{ width: '100%' }"
/>
</el-form-item>
<el-form-item
label="扩展值"
prop="extend"
>
<el-form-item label="扩展值" prop="extend">
<el-input
v-model="formData.extend"
placeholder="请输入扩展值"
clearable
:style="{width: '100%'}"
:style="{ width: '100%' }"
/>
</el-form-item>
<el-form-item
label="启用状态"
prop="status"
required
>
<el-form-item label="启用状态" prop="status" required>
<el-switch
v-model="formData.status"
active-text="开启"
inactive-text="停用"
/>
</el-form-item>
<el-form-item
label="排序标记"
prop="sort"
>
<el-form-item label="排序标记" prop="sort">
<el-input-number
v-model.number="formData.sort"
placeholder="排序标记"
@@ -191,172 +146,173 @@
</template>
<script setup>
import {
createSysDictionaryDetail,
deleteSysDictionaryDetail,
updateSysDictionaryDetail,
findSysDictionaryDetail,
getSysDictionaryDetailList
} from '@/api/sysDictionaryDetail' // 此处请自行替换地址
import { ref, watch } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { formatBoolean, formatDate } from '@/utils/format'
import {
createSysDictionaryDetail,
deleteSysDictionaryDetail,
updateSysDictionaryDetail,
findSysDictionaryDetail,
getSysDictionaryDetailList
} from '@/api/sysDictionaryDetail' // 此处请自行替换地址
import { ref, watch } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { formatBoolean, formatDate } from '@/utils/format'
defineOptions({
name: 'SysDictionaryDetail'
})
const props = defineProps({
sysDictionaryID: {
type: Number,
default: 0
}
})
const formData = ref({
label: null,
value: null,
status: true,
sort: null
})
const rules = ref({
label: [
{
required: true,
message: '请输入展示值',
trigger: 'blur'
}
],
value: [
{
required: true,
message: '请输入字典值',
trigger: 'blur'
}
],
sort: [
{
required: true,
message: '排序标记',
trigger: 'blur'
}
]
})
const page = ref(1)
const total = ref(0)
const pageSize = ref(10)
const tableData = ref([])
// 分页
const handleSizeChange = (val) => {
pageSize.value = val
getTableData()
}
const handleCurrentChange = (val) => {
page.value = val
getTableData()
}
// 查询
const getTableData = async() => {
if(!props.sysDictionaryID) return
const table = await getSysDictionaryDetailList({
page: page.value,
pageSize: pageSize.value,
sysDictionaryID: props.sysDictionaryID
defineOptions({
name: 'SysDictionaryDetail'
})
if (table.code === 0) {
tableData.value = table.data.list
total.value = table.data.total
page.value = table.data.page
pageSize.value = table.data.pageSize
}
}
getTableData()
const props = defineProps({
sysDictionaryID: {
type: Number,
default: 0
}
})
const type = ref('')
const drawerFormVisible = ref(false)
const updateSysDictionaryDetailFunc = async(row) => {
drawerForm.value && drawerForm.value.clearValidate()
const res = await findSysDictionaryDetail({ ID: row.ID })
type.value = 'update'
if (res.code === 0) {
formData.value = res.data.reSysDictionaryDetail
drawerFormVisible.value = true
}
}
const closeDrawer = () => {
drawerFormVisible.value = false
formData.value = {
const formData = ref({
label: null,
value: null,
status: true,
sort: null,
sysDictionaryID: props.sysDictionaryID
}
}
const deleteSysDictionaryDetailFunc = async(row) => {
ElMessageBox.confirm('确定要删除吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(async() => {
const res = await deleteSysDictionaryDetail({ ID: row.ID })
if (res.code === 0) {
ElMessage({
type: 'success',
message: '删除成功'
})
if (tableData.value.length === 1 && page.value > 1) {
page.value--
sort: null
})
const rules = ref({
label: [
{
required: true,
message: '请输入展示值',
trigger: 'blur'
}
getTableData()
}
],
value: [
{
required: true,
message: '请输入字典值',
trigger: 'blur'
}
],
sort: [
{
required: true,
message: '排序标记',
trigger: 'blur'
}
]
})
}
const drawerForm = ref(null)
const enterDrawer = async() => {
drawerForm.value.validate(async valid => {
formData.value.sysDictionaryID = props.sysDictionaryID
if (!valid) return
let res
switch (type.value) {
case 'create':
res = await createSysDictionaryDetail(formData.value)
break
case 'update':
res = await updateSysDictionaryDetail(formData.value)
break
default:
res = await createSysDictionaryDetail(formData.value)
break
const page = ref(1)
const total = ref(0)
const pageSize = ref(10)
const tableData = ref([])
// 分页
const handleSizeChange = (val) => {
pageSize.value = val
getTableData()
}
const handleCurrentChange = (val) => {
page.value = val
getTableData()
}
// 查询
const getTableData = async () => {
if (!props.sysDictionaryID) return
const table = await getSysDictionaryDetailList({
page: page.value,
pageSize: pageSize.value,
sysDictionaryID: props.sysDictionaryID
})
if (table.code === 0) {
tableData.value = table.data.list
total.value = table.data.total
page.value = table.data.page
pageSize.value = table.data.pageSize
}
if (res.code === 0) {
ElMessage({
type: 'success',
message: '创建/更改成功'
})
closeDrawer()
getTableData()
}
})
}
const openDrawer = () => {
type.value = 'create'
drawerForm.value && drawerForm.value.clearValidate()
drawerFormVisible.value = true
}
}
watch(() => props.sysDictionaryID, () => {
getTableData()
})
const type = ref('')
const drawerFormVisible = ref(false)
const updateSysDictionaryDetailFunc = async (row) => {
drawerForm.value && drawerForm.value.clearValidate()
const res = await findSysDictionaryDetail({ ID: row.ID })
type.value = 'update'
if (res.code === 0) {
formData.value = res.data.reSysDictionaryDetail
drawerFormVisible.value = true
}
}
const closeDrawer = () => {
drawerFormVisible.value = false
formData.value = {
label: null,
value: null,
status: true,
sort: null,
sysDictionaryID: props.sysDictionaryID
}
}
const deleteSysDictionaryDetailFunc = async (row) => {
ElMessageBox.confirm('确定要删除吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(async () => {
const res = await deleteSysDictionaryDetail({ ID: row.ID })
if (res.code === 0) {
ElMessage({
type: 'success',
message: '删除成功'
})
if (tableData.value.length === 1 && page.value > 1) {
page.value--
}
getTableData()
}
})
}
const drawerForm = ref(null)
const enterDrawer = async () => {
drawerForm.value.validate(async (valid) => {
formData.value.sysDictionaryID = props.sysDictionaryID
if (!valid) return
let res
switch (type.value) {
case 'create':
res = await createSysDictionaryDetail(formData.value)
break
case 'update':
res = await updateSysDictionaryDetail(formData.value)
break
default:
res = await createSysDictionaryDetail(formData.value)
break
}
if (res.code === 0) {
ElMessage({
type: 'success',
message: '创建/更改成功'
})
closeDrawer()
getTableData()
}
})
}
const openDrawer = () => {
type.value = 'create'
drawerForm.value && drawerForm.value.clearValidate()
drawerFormVisible.value = true
}
watch(
() => props.sysDictionaryID,
() => {
getTableData()
}
)
</script>
<style>
</style>
<style></style>
+6 -9
View File
@@ -1,10 +1,7 @@
<template>
<div>
<router-view v-slot="{ Component }">
<transition
mode="out-in"
name="el-fade-in-linear"
>
<transition mode="out-in" name="el-fade-in-linear">
<keep-alive :include="routerStore.keepAliveRouters">
<component :is="Component" />
</keep-alive>
@@ -14,10 +11,10 @@
</template>
<script setup>
import { useRouterStore } from '@/pinia/modules/router'
const routerStore = useRouterStore()
import { useRouterStore } from '@/pinia/modules/router'
const routerStore = useRouterStore()
defineOptions({
name: 'SuperAdmin'
})
defineOptions({
name: 'SuperAdmin'
})
</script>
@@ -1,123 +1,131 @@
<template>
<div class="flex justify-between items-center gap-2 w-full">
<el-cascader
v-if="pathIsSelect"
placeholder="请选择文件路径"
:options="pathOptions"
v-model="activeComponent"
filterable
class="w-full"
clearable
@change="emitChange"
v-if="pathIsSelect"
placeholder="请选择文件路径"
:options="pathOptions"
v-model="activeComponent"
filterable
class="w-full"
clearable
@change="emitChange"
/>
<el-input v-else v-model="tempPath" placeholder="页面:view/xxx/xx.vue 插件:plugin/xx/xx.vue" @change="emitChange" />
<el-button @click="togglePathIsSelect">{{ pathIsSelect ? '手动输入' : '快捷选择' }} </el-button>
<el-input
v-else
v-model="tempPath"
placeholder="页面:view/xxx/xx.vue 插件:plugin/xx/xx.vue"
@change="emitChange"
/>
<el-button @click="togglePathIsSelect"
>{{ pathIsSelect ? '手动输入' : '快捷选择' }}
</el-button>
</div>
</template>
<script setup>
import { onMounted, ref, watch } from "vue";
import pathInfo from "@/pathInfo.json";
import { onMounted, ref, watch } from 'vue'
import pathInfo from '@/pathInfo.json'
const props = defineProps({
component: {
type: String,
default: ""
}
})
const emits = defineEmits(['change'])
const pathOptions = ref([])
const tempPath = ref('')
const activeComponent = ref([])
const pathIsSelect = ref(true)
const togglePathIsSelect = () => {
if(pathIsSelect.value){
tempPath.value = activeComponent.value?.join('/') || ''
}else{
activeComponent.value = tempPath.value?.split('/') || []
}
pathIsSelect.value = !pathIsSelect.value
emitChange()
}
function convertToCascaderOptions(data) {
const result = [];
for (const path in data) {
const label = data[path];
const parts = path.split('/').filter(Boolean);
// 如果第一个部分是 'src',则从第二个部分开始处理
const startIndex = parts[0] === 'src' ? 1 : 0;
let currentLevel = result;
for (let i = startIndex; i < parts.length; i++) {
const part = parts[i];
let node = currentLevel.find(item => item.value === part);
if (!node) {
node = {
value: part,
label: part,
children: []
};
currentLevel.push(node);
}
if (i === parts.length - 1) {
// 如果是路径的最后一部分,设置标签并移除 children
node.label = label;
delete node.children;
}
currentLevel = node.children || [];
const props = defineProps({
component: {
type: String,
default: ''
}
})
const emits = defineEmits(['change'])
const pathOptions = ref([])
const tempPath = ref('')
const activeComponent = ref([])
const pathIsSelect = ref(true)
const togglePathIsSelect = () => {
if (pathIsSelect.value) {
tempPath.value = activeComponent.value?.join('/') || ''
} else {
activeComponent.value = tempPath.value?.split('/') || []
}
pathIsSelect.value = !pathIsSelect.value
emitChange()
}
return result;
}
function convertToCascaderOptions(data) {
const result = []
for (const path in data) {
const label = data[path]
const parts = path.split('/').filter(Boolean)
watch(() => props.component, (value) => {
initCascader(value)
})
// 如果第一个部分是 'src',则从第二个部分开始处理
const startIndex = parts[0] === 'src' ? 1 : 0
onMounted(() => {
pathOptions.value = convertToCascaderOptions(pathInfo)
initCascader(props.component)
})
let currentLevel = result
const initCascader = (value) => {
// 新增的时候
if(value === ''){
pathIsSelect.value = true
return
for (let i = startIndex; i < parts.length; i++) {
const part = parts[i]
let node = currentLevel.find((item) => item.value === part)
if (!node) {
node = {
value: part,
label: part,
children: []
}
currentLevel.push(node)
}
if (i === parts.length - 1) {
// 如果是路径的最后一部分,设置标签并移除 children
node.label = label
delete node.children
}
currentLevel = node.children || []
}
}
return result
}
// 编辑的时候,根据路径判断是选择框还是输入框
if (pathInfo[`/src/${value}`]) {
activeComponent.value = value.split('/').filter(Boolean);
tempPath.value = ''
pathIsSelect.value = true
return
}
tempPath.value = value
activeComponent.value = []
pathIsSelect.value = false
}
watch(
() => props.component,
(value) => {
initCascader(value)
}
)
const emitChange = () => {
emits('change', pathIsSelect.value ? activeComponent.value?.join('/') : tempPath.value)
}
onMounted(() => {
pathOptions.value = convertToCascaderOptions(pathInfo)
initCascader(props.component)
})
const initCascader = (value) => {
// 新增的时候
if (value === '') {
pathIsSelect.value = true
return
}
// 编辑的时候,根据路径判断是选择框还是输入框
if (pathInfo[`/src/${value}`]) {
activeComponent.value = value.split('/').filter(Boolean)
tempPath.value = ''
pathIsSelect.value = true
return
}
tempPath.value = value
activeComponent.value = []
pathIsSelect.value = false
}
const emitChange = () => {
emits(
'change',
pathIsSelect.value ? activeComponent.value?.join('/') : tempPath.value
)
}
</script>
<style scoped lang="scss">
</style>
<style scoped lang="scss"></style>
File diff suppressed because it is too large Load Diff
+286 -408
View File
@@ -2,26 +2,14 @@
<div>
<div class="gva-table-box">
<div class="gva-btn-list">
<el-button
type="primary"
icon="plus"
@click="addMenu(0)"
>
<el-button type="primary" icon="plus" @click="addMenu(0)">
新增根菜单
</el-button>
</div>
<!-- 由于此处菜单跟左侧列表一一对应所以不需要分页 pageSize默认999 -->
<el-table
:data="tableData"
row-key="ID"
>
<el-table-column
align="left"
label="ID"
min-width="100"
prop="ID"
/>
<el-table :data="tableData" row-key="ID">
<el-table-column align="left" label="ID" min-width="100" prop="ID" />
<el-table-column
align="left"
label="展示名称"
@@ -39,10 +27,7 @@
prop="authorityName"
>
<template #default="scope">
<div
v-if="scope.row.meta.icon"
class="icon-column"
>
<div v-if="scope.row.meta.icon" class="icon-column">
<el-icon>
<component :is="scope.row.meta.icon" />
</el-icon>
@@ -71,7 +56,7 @@
prop="hidden"
>
<template #default="scope">
<span>{{ scope.row.hidden ? "隐藏" : "显示" }}</span>
<span>{{ scope.row.hidden ? '隐藏' : '显示' }}</span>
</template>
</el-table-column>
<el-table-column
@@ -80,24 +65,14 @@
min-width="90"
prop="parentId"
/>
<el-table-column
align="left"
label="排序"
min-width="70"
prop="sort"
/>
<el-table-column align="left" label="排序" min-width="70" prop="sort" />
<el-table-column
align="left"
label="文件路径"
min-width="360"
prop="component"
/>
<el-table-column
align="left"
fixed="right"
label="操作"
width="300"
>
<el-table-column align="left" fixed="right" label="操作" width="300">
<template #default="scope">
<el-button
type="primary"
@@ -137,15 +112,8 @@
<div class="flex justify-between items-center">
<span class="text-lg">{{ dialogTitle }}</span>
<div>
<el-button @click="closeDialog">
取 消
</el-button>
<el-button
type="primary"
@click="enterDialog"
>
确 定
</el-button>
<el-button @click="closeDialog"> 取 消 </el-button>
<el-button type="primary" @click="enterDialog"> 确 定 </el-button>
</div>
</div>
</template>
@@ -161,12 +129,14 @@
>
<el-row class="w-full">
<el-col :span="16">
<el-form-item
label="文件路径"
prop="component"
>
<components-cascader :component="form.component" @change="fmtComponent" />
<span style="font-size: 12px; margin-right: 12px">如果菜单包含子菜单,请创建router-view二级路由页面或者</span>
<el-form-item label="文件路径" prop="component">
<components-cascader
:component="form.component"
@change="fmtComponent"
/>
<span style="font-size: 12px; margin-right: 12px"
>如果菜单包含子菜单,请创建router-view二级路由页面或者</span
>
<el-button
style="margin-top: 4px"
@click="form.component = 'view/routerHolder.vue'"
@@ -176,23 +146,14 @@
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item
label="展示名称"
prop="meta.title"
>
<el-input
v-model="form.meta.title"
autocomplete="off"
/>
<el-form-item label="展示名称" prop="meta.title">
<el-input v-model="form.meta.title" autocomplete="off" />
</el-form-item>
</el-col>
</el-row>
<el-row class="w-full">
<el-col :span="8">
<el-form-item
label="路由Name"
prop="path"
>
<el-form-item label="路由Name" prop="path">
<el-input
v-model="form.name"
autocomplete="off"
@@ -202,16 +163,15 @@
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item
prop="path"
>
<el-form-item prop="path">
<template #label>
<span style="display: inline-flex; align-items: center">
<span>路由Path</span>
<el-checkbox
v-model="checkFlag"
style="margin-left: 12px; height: auto"
>添加参数</el-checkbox>
>添加参数</el-checkbox
>
</span>
</template>
@@ -224,31 +184,21 @@
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item
label="是否隐藏"
>
<el-form-item label="是否隐藏">
<el-select
v-model="form.hidden"
style="width: 100%"
placeholder="是否在列表隐藏"
>
<el-option
:value="false"
label="否"
/>
<el-option
:value="true"
label="是"
/>
<el-option :value="false" label="否" />
<el-option :value="true" label="是" />
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row class="w-full">
<el-col :span="8">
<el-form-item
label="父节点ID"
>
<el-form-item label="父节点ID">
<el-cascader
v-model="form.parentId"
style="width: 100%"
@@ -259,7 +209,7 @@
label: 'title',
value: 'ID',
disabled: 'disabled',
emitPath: false,
emitPath: false
}"
:show-all-levels="false"
filterable
@@ -267,32 +217,19 @@
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item
label="图标"
prop="meta.icon"
>
<icon
v-model="form.meta.icon"
/>
<el-form-item label="图标" prop="meta.icon">
<icon v-model="form.meta.icon" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item
label="排序标记"
prop="sort"
>
<el-input
v-model.number="form.sort"
autocomplete="off"
/>
<el-form-item label="排序标记" prop="sort">
<el-input v-model.number="form.sort" autocomplete="off" />
</el-form-item>
</el-col>
</el-row>
<el-row class="w-full">
<el-col :span="8">
<el-form-item
prop="meta.activeName"
>
<el-form-item prop="meta.activeName">
<template #label>
<div>
<span> 高亮菜单 </span>
@@ -313,44 +250,26 @@
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item
label="KeepAlive"
prop="meta.keepAlive"
>
<el-form-item label="KeepAlive" prop="meta.keepAlive">
<el-select
v-model="form.meta.keepAlive"
style="width: 100%"
placeholder="是否keepAlive缓存页面"
>
<el-option
:value="false"
label="否"
/>
<el-option
:value="true"
label="是"
/>
<el-option :value="false" label="否" />
<el-option :value="true" label="是" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item
label="CloseTab"
prop="meta.closeTab"
>
<el-form-item label="CloseTab" prop="meta.closeTab">
<el-select
v-model="form.meta.closeTab"
style="width: 100%"
placeholder="是否自动关闭tab"
>
<el-option
:value="false"
label="否"
/>
<el-option
:value="true"
label="是"
/>
<el-option :value="false" label="否" />
<el-option :value="true" label="是" />
</el-select>
</el-form-item>
</el-col>
@@ -376,14 +295,8 @@
style="width: 100%"
placeholder="是否为基础页面"
>
<el-option
:value="false"
label="否"
/>
<el-option
:value="true"
label="是"
/>
<el-option :value="false" label="否" />
<el-option :value="true" label="是" />
</el-select>
</el-form-item>
</el-col>
@@ -391,18 +304,11 @@
</el-form>
<div>
<div class="flex items-center gap-2">
<el-button
type="primary"
icon="edit"
@click="addParameter(form)"
>
<el-button type="primary" icon="edit" @click="addParameter(form)">
新增菜单参数
</el-button>
</div>
<el-table
:data="form.parameters"
style="width: 100%; margin-top: 12px"
>
<el-table :data="form.parameters" style="width: 100%; margin-top: 12px">
<el-table-column
align="left"
prop="type"
@@ -410,40 +316,20 @@
width="180"
>
<template #default="scope">
<el-select
v-model="scope.row.type"
placeholder="请选择"
>
<el-option
key="query"
value="query"
label="query"
/>
<el-option
key="params"
value="params"
label="params"
/>
<el-select v-model="scope.row.type" placeholder="请选择">
<el-option key="query" value="query" label="query" />
<el-option key="params" value="params" label="params" />
</el-select>
</template>
</el-table-column>
<el-table-column
align="left"
prop="key"
label="参数key"
width="180"
>
<el-table-column align="left" prop="key" label="参数key" width="180">
<template #default="scope">
<div>
<el-input v-model="scope.row.key" />
</div>
</template>
</el-table-column>
<el-table-column
align="left"
prop="value"
label="参数值"
>
<el-table-column align="left" prop="value" label="参数值">
<template #default="scope">
<div>
<el-input v-model="scope.row.value" />
@@ -466,11 +352,7 @@
</el-table>
<div class="flex items-center gap-2 mt-3">
<el-button
type="primary"
icon="edit"
@click="addBtn(form)"
>
<el-button type="primary" icon="edit" @click="addBtn(form)">
新增可控按钮
</el-button>
<el-icon
@@ -483,10 +365,7 @@
</el-icon>
</div>
<el-table
:data="form.menuBtn"
style="width: 100%; margin-top: 12px"
>
<el-table :data="form.menuBtn" style="width: 100%; margin-top: 12px">
<el-table-column
align="left"
prop="name"
@@ -499,12 +378,7 @@
</div>
</template>
</el-table-column>
<el-table-column
align="left"
prop="name"
label="备注"
width="180"
>
<el-table-column align="left" prop="name" label="备注" width="180">
<template #default="scope">
<div>
<el-input v-model="scope.row.desc" />
@@ -531,152 +405,95 @@
</template>
<script setup>
import {
updateBaseMenu,
getMenuList,
addBaseMenu,
deleteBaseMenu,
getBaseMenuById,
} from '@/api/menu'
import icon from '@/view/superAdmin/menu/icon.vue'
import WarningBar from '@/components/warningBar/warningBar.vue'
import { canRemoveAuthorityBtnApi } from '@/api/authorityBtn'
import {reactive, ref} from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { QuestionFilled } from '@element-plus/icons-vue'
import { toDoc } from '@/utils/doc'
import {toLowerCase} from "@/utils/stringFun";
import ComponentsCascader from "@/view/superAdmin/menu/components/components-cascader.vue";
import {
updateBaseMenu,
getMenuList,
addBaseMenu,
deleteBaseMenu,
getBaseMenuById
} from '@/api/menu'
import icon from '@/view/superAdmin/menu/icon.vue'
import WarningBar from '@/components/warningBar/warningBar.vue'
import { canRemoveAuthorityBtnApi } from '@/api/authorityBtn'
import { reactive, ref } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { QuestionFilled } from '@element-plus/icons-vue'
import { toDoc } from '@/utils/doc'
import { toLowerCase } from '@/utils/stringFun'
import ComponentsCascader from '@/view/superAdmin/menu/components/components-cascader.vue'
import pathInfo from "@/pathInfo.json";
import pathInfo from '@/pathInfo.json'
defineOptions({
name: 'Menus',
})
const rules = reactive({
path: [{ required: true, message: '请输入菜单name', trigger: 'blur' }],
component: [{ required: true, message: '请输入文件路径', trigger: 'blur' }],
'meta.title': [
{ required: true, message: '请输入菜单展示名称', trigger: 'blur' },
],
})
const tableData = ref([])
// 查询
const getTableData = async() => {
const table = await getMenuList()
if (table.code === 0) {
tableData.value = table.data
}
}
getTableData()
// 新增参数
const addParameter = (form) => {
if (!form.parameters) {
form.parameters = []
}
form.parameters.push({
type: 'query',
key: '',
value: '',
defineOptions({
name: 'Menus'
})
}
const fmtComponent = (component) => {
form.value.component = component.replace(/\\/g, '/')
form.value.name = toLowerCase(pathInfo["/src/"+component])
form.value.path = form.value.name
}
// 删除参数
const deleteParameter = (parameters, index) => {
parameters.splice(index, 1)
}
// 新增可控按钮
const addBtn = (form) => {
if (!form.menuBtn) {
form.menuBtn = []
}
form.menuBtn.push({
name: '',
desc: '',
const rules = reactive({
path: [{ required: true, message: '请输入菜单name', trigger: 'blur' }],
component: [{ required: true, message: '请输入文件路径', trigger: 'blur' }],
'meta.title': [
{ required: true, message: '请输入菜单展示名称', trigger: 'blur' }
]
})
}
// 删除可控按钮
const deleteBtn = async(btns, index) => {
const btn = btns[index]
if (btn.ID === 0) {
btns.splice(index, 1)
return
const tableData = ref([])
// 查询
const getTableData = async () => {
const table = await getMenuList()
if (table.code === 0) {
tableData.value = table.data
}
}
const res = await canRemoveAuthorityBtnApi({ id: btn.ID })
if (res.code === 0) {
btns.splice(index, 1)
}
}
const form = ref({
ID: 0,
path: '',
name: '',
hidden: false,
parentId: 0,
component: '',
meta: {
activeName: '',
title: '',
icon: '',
defaultMenu: false,
closeTab: false,
keepAlive: false,
},
parameters: [],
menuBtn: [],
})
const changeName = () => {
form.value.path = form.value.name
}
getTableData()
const handleClose = (done) => {
initForm()
done()
}
// 删除菜单
const deleteMenu = (ID) => {
ElMessageBox.confirm('此操作将永久删除所有角色下该菜单, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
})
.then(async() => {
const res = await deleteBaseMenu({ ID })
if (res.code === 0) {
ElMessage({
type: 'success',
message: '删除成功!',
})
getTableData()
}
// 新增参数
const addParameter = (form) => {
if (!form.parameters) {
form.parameters = []
}
form.parameters.push({
type: 'query',
key: '',
value: ''
})
.catch(() => {
ElMessage({
type: 'info',
message: '已取消删除',
})
}
const fmtComponent = (component) => {
form.value.component = component.replace(/\\/g, '/')
form.value.name = toLowerCase(pathInfo['/src/' + component])
form.value.path = form.value.name
}
// 删除参数
const deleteParameter = (parameters, index) => {
parameters.splice(index, 1)
}
// 新增可控按钮
const addBtn = (form) => {
if (!form.menuBtn) {
form.menuBtn = []
}
form.menuBtn.push({
name: '',
desc: ''
})
}
// 初始化弹窗内表格方法
const menuForm = ref(null)
const checkFlag = ref(false)
const initForm = () => {
checkFlag.value = false
menuForm.value.resetFields()
form.value = {
}
// 删除可控按钮
const deleteBtn = async (btns, index) => {
const btn = btns[index]
if (btn.ID === 0) {
btns.splice(index, 1)
return
}
const res = await canRemoveAuthorityBtnApi({ id: btn.ID })
if (res.code === 0) {
btns.splice(index, 1)
}
}
const form = ref({
ID: 0,
path: '',
name: '',
@@ -684,116 +501,177 @@ const initForm = () => {
parentId: 0,
component: '',
meta: {
activeName: '',
title: '',
icon: '',
defaultMenu: false,
closeTab: false,
keepAlive: false,
keepAlive: false
},
}
}
// 关闭弹窗
const dialogFormVisible = ref(false)
const closeDialog = () => {
initForm()
dialogFormVisible.value = false
}
// 添加menu
const enterDialog = async() => {
menuForm.value.validate(async(valid) => {
if (valid) {
let res
if (isEdit.value) {
res = await updateBaseMenu(form.value)
} else {
res = await addBaseMenu(form.value)
}
if (res.code === 0) {
ElMessage({
type: 'success',
message: isEdit.value ? '编辑成功' : '添加成功!',
})
getTableData()
}
initForm()
dialogFormVisible.value = false
}
parameters: [],
menuBtn: []
})
}
const changeName = () => {
form.value.path = form.value.name
}
const menuOption = ref([
{
ID: '0',
title: '根菜单',
},
])
const setOptions = () => {
menuOption.value = [
{
const handleClose = (done) => {
initForm()
done()
}
// 删除菜单
const deleteMenu = (ID) => {
ElMessageBox.confirm(
'此操作将永久删除所有角色下该菜单, 是否继续?',
'提示',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}
)
.then(async () => {
const res = await deleteBaseMenu({ ID })
if (res.code === 0) {
ElMessage({
type: 'success',
message: '删除成功!'
})
getTableData()
}
})
.catch(() => {
ElMessage({
type: 'info',
message: '已取消删除'
})
})
}
// 初始化弹窗内表格方法
const menuForm = ref(null)
const checkFlag = ref(false)
const initForm = () => {
checkFlag.value = false
menuForm.value.resetFields()
form.value = {
ID: 0,
title: '根目录',
},
]
setMenuOptions(tableData.value, menuOption.value, false)
}
const setMenuOptions = (menuData, optionsData, disabled) => {
menuData &&
menuData.forEach((item) => {
if (item.children && item.children.length) {
const option = {
title: item.meta.title,
ID: item.ID,
disabled: disabled || item.ID === form.value.ID,
children: [],
path: '',
name: '',
hidden: false,
parentId: 0,
component: '',
meta: {
title: '',
icon: '',
defaultMenu: false,
closeTab: false,
keepAlive: false
}
}
}
// 关闭弹窗
const dialogFormVisible = ref(false)
const closeDialog = () => {
initForm()
dialogFormVisible.value = false
}
// 添加menu
const enterDialog = async () => {
menuForm.value.validate(async (valid) => {
if (valid) {
let res
if (isEdit.value) {
res = await updateBaseMenu(form.value)
} else {
res = await addBaseMenu(form.value)
}
setMenuOptions(
item.children,
option.children,
disabled || item.ID === form.value.ID
)
optionsData.push(option)
} else {
const option = {
title: item.meta.title,
ID: item.ID,
disabled: disabled || item.ID === form.value.ID,
if (res.code === 0) {
ElMessage({
type: 'success',
message: isEdit.value ? '编辑成功' : '添加成功!'
})
getTableData()
}
optionsData.push(option)
initForm()
dialogFormVisible.value = false
}
})
}
}
// 添加菜单方法,id为 0则为添加根菜单
const isEdit = ref(false)
const dialogTitle = ref('新增菜单')
const addMenu = (id) => {
dialogTitle.value = '新增菜单'
form.value.parentId = id
isEdit.value = false
setOptions()
dialogFormVisible.value = true
}
// 修改菜单方法
const editMenu = async(id) => {
dialogTitle.value = '编辑菜单'
const res = await getBaseMenuById({ id })
form.value = res.data.menu
isEdit.value = true
setOptions()
dialogFormVisible.value = true
}
const menuOption = ref([
{
ID: '0',
title: '根菜单'
}
])
const setOptions = () => {
menuOption.value = [
{
ID: 0,
title: '根目录'
}
]
setMenuOptions(tableData.value, menuOption.value, false)
}
const setMenuOptions = (menuData, optionsData, disabled) => {
menuData &&
menuData.forEach((item) => {
if (item.children && item.children.length) {
const option = {
title: item.meta.title,
ID: item.ID,
disabled: disabled || item.ID === form.value.ID,
children: []
}
setMenuOptions(
item.children,
option.children,
disabled || item.ID === form.value.ID
)
optionsData.push(option)
} else {
const option = {
title: item.meta.title,
ID: item.ID,
disabled: disabled || item.ID === form.value.ID
}
optionsData.push(option)
}
})
}
// 添加菜单方法,id为 0则为添加根菜单
const isEdit = ref(false)
const dialogTitle = ref('新增菜单')
const addMenu = (id) => {
dialogTitle.value = '新增菜单'
form.value.parentId = id
isEdit.value = false
setOptions()
dialogFormVisible.value = true
}
// 修改菜单方法
const editMenu = async (id) => {
dialogTitle.value = '编辑菜单'
const res = await getBaseMenuById({ id })
form.value = res.data.menu
isEdit.value = true
setOptions()
dialogFormVisible.value = true
}
</script>
<style scoped lang="scss">
.warning {
color: #dc143c;
}
.icon-column {
display: flex;
align-items: center;
.el-icon {
margin-right: 8px;
.warning {
color: #dc143c;
}
.icon-column {
display: flex;
align-items: center;
.el-icon {
margin-right: 8px;
}
}
}
</style>
@@ -1,38 +1,21 @@
<template>
<div>
<div class="gva-search-box">
<el-form
:inline="true"
:model="searchInfo"
>
<el-form :inline="true" :model="searchInfo">
<el-form-item label="请求方法">
<el-input
v-model="searchInfo.method"
placeholder="搜索条件"
/>
<el-input v-model="searchInfo.method" placeholder="搜索条件" />
</el-form-item>
<el-form-item label="请求路径">
<el-input
v-model="searchInfo.path"
placeholder="搜索条件"
/>
<el-input v-model="searchInfo.path" placeholder="搜索条件" />
</el-form-item>
<el-form-item label="结果状态码">
<el-input
v-model="searchInfo.status"
placeholder="搜索条件"
/>
<el-input v-model="searchInfo.status" placeholder="搜索条件" />
</el-form-item>
<el-form-item>
<el-button
type="primary"
icon="search"
@click="onSubmit"
>查询</el-button>
<el-button
icon="refresh"
@click="onReset"
>重置</el-button>
<el-button type="primary" icon="search" @click="onSubmit"
>查询</el-button
>
<el-button icon="refresh" @click="onReset">重置</el-button>
</el-form-item>
</el-form>
</div>
@@ -42,7 +25,8 @@
icon="delete"
:disabled="!multipleSelection.length"
@click="onDelete"
>删除</el-button>
>删除</el-button
>
</div>
<el-table
ref="multipleTable"
@@ -52,45 +36,27 @@
row-key="ID"
@selection-change="handleSelectionChange"
>
<el-table-column
align="left"
type="selection"
width="55"
/>
<el-table-column
align="left"
label="操作人"
width="140"
>
<el-table-column align="left" type="selection" width="55" />
<el-table-column align="left" label="操作人" width="140">
<template #default="scope">
<div>{{ scope.row.user.userName }}({{ scope.row.user.nickName }})</div>
<div>
{{ scope.row.user.userName }}({{ scope.row.user.nickName }})
</div>
</template>
</el-table-column>
<el-table-column
align="left"
label="日期"
width="180"
>
<template #default="scope">{{ formatDate(scope.row.CreatedAt) }}</template>
<el-table-column align="left" label="日期" width="180">
<template #default="scope">{{
formatDate(scope.row.CreatedAt)
}}</template>
</el-table-column>
<el-table-column
align="left"
label="状态码"
prop="status"
width="120"
>
<el-table-column align="left" label="状态码" prop="status" width="120">
<template #default="scope">
<div>
<el-tag type="success">{{ scope.row.status }}</el-tag>
</div>
</template>
</el-table-column>
<el-table-column
align="left"
label="请求IP"
prop="ip"
width="120"
/>
<el-table-column align="left" label="请求IP" prop="ip" width="120" />
<el-table-column
align="left"
label="请求方法"
@@ -103,12 +69,7 @@
prop="path"
width="240"
/>
<el-table-column
align="left"
label="请求"
prop="path"
width="80"
>
<el-table-column align="left" label="请求" prop="path" width="80">
<template #default="scope">
<div>
<el-popover
@@ -120,7 +81,7 @@
<pre>{{ fmtBody(scope.row.body) }}</pre>
</div>
<template #reference>
<el-icon style="cursor: pointer;"><warning /></el-icon>
<el-icon style="cursor: pointer"><warning /></el-icon>
</template>
</el-popover>
@@ -128,12 +89,7 @@
</div>
</template>
</el-table-column>
<el-table-column
align="left"
label="响应"
prop="path"
width="80"
>
<el-table-column align="left" label="响应" prop="path" width="80">
<template #default="scope">
<div>
<el-popover
@@ -145,24 +101,22 @@
<pre>{{ fmtBody(scope.row.resp) }}</pre>
</div>
<template #reference>
<el-icon style="cursor: pointer;"><warning /></el-icon>
<el-icon style="cursor: pointer"><warning /></el-icon>
</template>
</el-popover>
<span v-else>无</span>
</div>
</template>
</el-table-column>
<el-table-column
align="left"
label="操作"
>
<el-table-column align="left" label="操作">
<template #default="scope">
<el-button
icon="delete"
type="primary"
link
@click="deleteSysOperationRecordFunc(scope.row)"
>删除</el-button>
>删除</el-button
>
</template>
</el-table-column>
</el-table>
@@ -182,144 +136,143 @@
</template>
<script setup>
import {
deleteSysOperationRecord,
getSysOperationRecordList,
deleteSysOperationRecordByIds
} from '@/api/sysOperationRecord' // 此处请自行替换地址
import { formatDate } from '@/utils/format'
import { ref } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import {
deleteSysOperationRecord,
getSysOperationRecordList,
deleteSysOperationRecordByIds
} from '@/api/sysOperationRecord' // 此处请自行替换地址
import { formatDate } from '@/utils/format'
import { ref } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
defineOptions({
name: 'SysOperationRecord'
})
const page = ref(1)
const total = ref(0)
const pageSize = ref(10)
const tableData = ref([])
const searchInfo = ref({})
const onReset = () => {
searchInfo.value = {}
}
// 条件搜索前端看此方法
const onSubmit = () => {
page.value = 1
pageSize.value = 10
if (searchInfo.value.status === '') {
searchInfo.value.status = null
}
getTableData()
}
// 分页
const handleSizeChange = (val) => {
pageSize.value = val
getTableData()
}
const handleCurrentChange = (val) => {
page.value = val
getTableData()
}
// 查询
const getTableData = async() => {
const table = await getSysOperationRecordList({
page: page.value,
pageSize: pageSize.value,
...searchInfo.value,
defineOptions({
name: 'SysOperationRecord'
})
if (table.code === 0) {
tableData.value = table.data.list
total.value = table.data.total
page.value = table.data.page
pageSize.value = table.data.pageSize
const page = ref(1)
const total = ref(0)
const pageSize = ref(10)
const tableData = ref([])
const searchInfo = ref({})
const onReset = () => {
searchInfo.value = {}
}
// 条件搜索前端看此方法
const onSubmit = () => {
page.value = 1
pageSize.value = 10
if (searchInfo.value.status === '') {
searchInfo.value.status = null
}
getTableData()
}
}
getTableData()
// 分页
const handleSizeChange = (val) => {
pageSize.value = val
getTableData()
}
const multipleSelection = ref([])
const handleSelectionChange = (val) => {
multipleSelection.value = val
}
const onDelete = async() => {
ElMessageBox.confirm('确定要删除吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(async() => {
const ids = []
multipleSelection.value &&
multipleSelection.value.forEach(item => {
const handleCurrentChange = (val) => {
page.value = val
getTableData()
}
// 查询
const getTableData = async () => {
const table = await getSysOperationRecordList({
page: page.value,
pageSize: pageSize.value,
...searchInfo.value
})
if (table.code === 0) {
tableData.value = table.data.list
total.value = table.data.total
page.value = table.data.page
pageSize.value = table.data.pageSize
}
}
getTableData()
const multipleSelection = ref([])
const handleSelectionChange = (val) => {
multipleSelection.value = val
}
const onDelete = async () => {
ElMessageBox.confirm('确定要删除吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(async () => {
const ids = []
multipleSelection.value &&
multipleSelection.value.forEach((item) => {
ids.push(item.ID)
})
const res = await deleteSysOperationRecordByIds({ ids })
if (res.code === 0) {
ElMessage({
type: 'success',
message: '删除成功'
})
if (tableData.value.length === ids.length && page.value > 1) {
page.value--
const res = await deleteSysOperationRecordByIds({ ids })
if (res.code === 0) {
ElMessage({
type: 'success',
message: '删除成功'
})
if (tableData.value.length === ids.length && page.value > 1) {
page.value--
}
getTableData()
}
getTableData()
}
})
}
const deleteSysOperationRecordFunc = async(row) => {
ElMessageBox.confirm('确定要删除吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(async() => {
const res = await deleteSysOperationRecord({ ID: row.ID })
if (res.code === 0) {
ElMessage({
type: 'success',
message: '删除成功'
})
if (tableData.value.length === 1 && page.value > 1) {
page.value--
})
}
const deleteSysOperationRecordFunc = async (row) => {
ElMessageBox.confirm('确定要删除吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(async () => {
const res = await deleteSysOperationRecord({ ID: row.ID })
if (res.code === 0) {
ElMessage({
type: 'success',
message: '删除成功'
})
if (tableData.value.length === 1 && page.value > 1) {
page.value--
}
getTableData()
}
getTableData()
})
}
const fmtBody = (value) => {
try {
return JSON.parse(value)
} catch (_) {
return value
}
})
}
const fmtBody = (value) => {
try {
return JSON.parse(value)
} catch (_) {
return value
}
}
</script>
<style lang="scss">
.table-expand {
padding-left: 60px;
font-size: 0;
label {
width: 90px;
color: #99a9bf;
.el-form-item {
margin-right: 0;
margin-bottom: 0;
width: 50%;
.table-expand {
padding-left: 60px;
font-size: 0;
label {
width: 90px;
color: #99a9bf;
.el-form-item {
margin-right: 0;
margin-bottom: 0;
width: 50%;
}
}
}
}
.popover-box {
background: #112435;
color: #f08047;
height: 600px;
width: 420px;
overflow: auto;
}
.popover-box::-webkit-scrollbar {
display: none; /* Chrome Safari */
}
.popover-box {
background: #112435;
color: #f08047;
height: 600px;
width: 420px;
overflow: auto;
}
.popover-box::-webkit-scrollbar {
display: none; /* Chrome Safari */
}
</style>
+495 -346
View File
@@ -1,29 +1,55 @@
<template>
<div>
<div class="gva-search-box">
<el-form ref="elSearchFormRef" :inline="true" :model="searchInfo" class="demo-form-inline" :rules="searchRule" @keyup.enter="onSubmit">
<el-form-item label="创建日期" prop="createdAt">
<template #label>
<span>
创建日期
<el-tooltip content="搜索范围是开始日期(包含)至结束日期(不包含)">
<el-icon><QuestionFilled /></el-icon>
</el-tooltip>
</span>
</template>
<el-date-picker v-model="searchInfo.startCreatedAt" type="datetime" placeholder="开始日期" :disabled-date="time=> searchInfo.endCreatedAt ? time.getTime() > searchInfo.endCreatedAt.getTime() : false"></el-date-picker>
—
<el-date-picker v-model="searchInfo.endCreatedAt" type="datetime" placeholder="结束日期" :disabled-date="time=> searchInfo.startCreatedAt ? time.getTime() < searchInfo.startCreatedAt.getTime() : false"></el-date-picker>
</el-form-item>
<el-form
ref="elSearchFormRef"
:inline="true"
:model="searchInfo"
class="demo-form-inline"
:rules="searchRule"
@keyup.enter="onSubmit"
>
<el-form-item label="创建日期" prop="createdAt">
<template #label>
<span>
创建日期
<el-tooltip
content="搜索范围是开始日期(包含)至结束日期(不包含)"
>
<el-icon><QuestionFilled /></el-icon>
</el-tooltip>
</span>
</template>
<el-date-picker
v-model="searchInfo.startCreatedAt"
type="datetime"
placeholder="开始日期"
:disabled-date="
(time) =>
searchInfo.endCreatedAt
? time.getTime() > searchInfo.endCreatedAt.getTime()
: false
"
></el-date-picker>
—
<el-date-picker
v-model="searchInfo.endCreatedAt"
type="datetime"
placeholder="结束日期"
:disabled-date="
(time) =>
searchInfo.startCreatedAt
? time.getTime() < searchInfo.startCreatedAt.getTime()
: false
"
></el-date-picker>
</el-form-item>
<el-form-item label="参数名称" prop="name">
<el-input v-model="searchInfo.name" placeholder="搜索条件" />
<el-input v-model="searchInfo.name" placeholder="搜索条件" />
</el-form-item>
<el-form-item label="参数键" prop="key">
<el-input v-model="searchInfo.key" placeholder="搜索条件" />
<el-input v-model="searchInfo.key" placeholder="搜索条件" />
</el-form-item>
<template v-if="showAllQuery">
@@ -31,290 +57,422 @@
</template>
<el-form-item>
<el-button type="primary" icon="search" @click="onSubmit">查询</el-button>
<el-button type="primary" icon="search" @click="onSubmit"
>查询</el-button
>
<el-button icon="refresh" @click="onReset">重置</el-button>
<el-button link type="primary" icon="arrow-down" @click="showAllQuery=true" v-if="!showAllQuery">展开</el-button>
<el-button link type="primary" icon="arrow-up" @click="showAllQuery=false" v-else>收起</el-button>
<el-button
link
type="primary"
icon="arrow-down"
@click="showAllQuery = true"
v-if="!showAllQuery"
>展开</el-button
>
<el-button
link
type="primary"
icon="arrow-up"
@click="showAllQuery = false"
v-else
>收起</el-button
>
</el-form-item>
</el-form>
</div>
<div class="gva-table-box">
<div class="gva-btn-list">
<el-button type="primary" icon="plus" @click="openDialog">新增</el-button>
<el-button icon="delete" style="margin-left: 10px;" :disabled="!multipleSelection.length" @click="onDelete">删除</el-button>
</div>
<el-table
<div class="gva-btn-list">
<el-button type="primary" icon="plus" @click="openDialog"
>新增</el-button
>
<el-button
icon="delete"
style="margin-left: 10px"
:disabled="!multipleSelection.length"
@click="onDelete"
>删除</el-button
>
</div>
<el-table
ref="multipleTable"
style="width: 100%"
tooltip-effect="dark"
:data="tableData"
row-key="ID"
@selection-change="handleSelectionChange"
>
>
<el-table-column type="selection" width="55" />
<el-table-column align="left" label="日期" prop="createdAt" width="180">
<template #default="scope">{{ formatDate(scope.row.CreatedAt) }}</template>
<template #default="scope">{{
formatDate(scope.row.CreatedAt)
}}</template>
</el-table-column>
<el-table-column align="left" label="参数名称" prop="name" width="120" />
<el-table-column align="left" label="参数键" prop="key" width="120" />
<el-table-column align="left" label="参数值" prop="value" width="120" />
<el-table-column align="left" label="参数说明" prop="desc" width="120" />
<el-table-column align="left" label="操作" fixed="right" min-width="240">
<template #default="scope">
<el-button type="primary" link class="table-button" @click="getDetails(scope.row)"><el-icon style="margin-right: 5px"><InfoFilled /></el-icon>查看详情</el-button>
<el-button type="primary" link icon="edit" class="table-button" @click="updateSysParamsFunc(scope.row)">变更</el-button>
<el-button type="primary" link icon="delete" @click="deleteRow(scope.row)">删除</el-button>
</template>
<el-table-column
align="left"
label="参数名称"
prop="name"
width="120"
/>
<el-table-column align="left" label="参数键" prop="key" width="120" />
<el-table-column align="left" label="参数值" prop="value" width="120" />
<el-table-column
align="left"
label="参数说明"
prop="desc"
width="120"
/>
<el-table-column
align="left"
label="操作"
fixed="right"
min-width="240"
>
<template #default="scope">
<el-button
type="primary"
link
class="table-button"
@click="getDetails(scope.row)"
><el-icon style="margin-right: 5px"><InfoFilled /></el-icon
>查看详情</el-button
>
<el-button
type="primary"
link
icon="edit"
class="table-button"
@click="updateSysParamsFunc(scope.row)"
>变更</el-button
>
<el-button
type="primary"
link
icon="delete"
@click="deleteRow(scope.row)"
>删除</el-button
>
</template>
</el-table-column>
</el-table>
<div class="gva-pagination">
<el-pagination
layout="total, sizes, prev, pager, next, jumper"
:current-page="page"
:page-size="pageSize"
:page-sizes="[10, 30, 50, 100]"
:total="total"
@current-change="handleCurrentChange"
@size-change="handleSizeChange"
/>
</div>
</el-table>
<div class="gva-pagination">
<el-pagination
layout="total, sizes, prev, pager, next, jumper"
:current-page="page"
:page-size="pageSize"
:page-sizes="[10, 30, 50, 100]"
:total="total"
@current-change="handleCurrentChange"
@size-change="handleSizeChange"
/>
</div>
</div>
<el-drawer destroy-on-close size="800" v-model="dialogFormVisible" :show-close="false" :before-close="closeDialog">
<template #header>
<div class="flex justify-between items-center">
<span class="text-lg">{{type==='create'?'添加':'修改'}}</span>
<div>
<el-button type="primary" @click="enterDialog">确 定</el-button>
<el-button @click="closeDialog">取 消</el-button>
</div>
</div>
</template>
<el-drawer
destroy-on-close
size="800"
v-model="dialogFormVisible"
:show-close="false"
:before-close="closeDialog"
>
<template #header>
<div class="flex justify-between items-center">
<span class="text-lg">{{ type === 'create' ? '添加' : '修改' }}</span>
<div>
<el-button type="primary" @click="enterDialog">确 定</el-button>
<el-button @click="closeDialog">取 消</el-button>
</div>
</div>
</template>
<el-form :model="formData" label-position="top" ref="elFormRef" :rules="rule" label-width="80px">
<el-form-item label="参数名称:" prop="name" >
<el-input v-model="formData.name" :clearable="true" placeholder="请输入参数名称" />
</el-form-item>
<el-form-item label="参数键:" prop="key" >
<el-input v-model="formData.key" :clearable="true" placeholder="请输入参数键" />
</el-form-item>
<el-form-item label="参数值:" prop="value" >
<el-input type="textarea" :rows="5" v-model="formData.value" :clearable="true" placeholder="请输入参数值" />
</el-form-item>
<el-form-item label="参数说明:" prop="desc" >
<el-input v-model="formData.desc" :clearable="true" placeholder="请输入参数说明" />
</el-form-item>
</el-form>
<el-form
:model="formData"
label-position="top"
ref="elFormRef"
:rules="rule"
label-width="80px"
>
<el-form-item label="参数名称:" prop="name">
<el-input
v-model="formData.name"
:clearable="true"
placeholder="请输入参数名称"
/>
</el-form-item>
<el-form-item label="参数键:" prop="key">
<el-input
v-model="formData.key"
:clearable="true"
placeholder="请输入参数键"
/>
</el-form-item>
<el-form-item label="参数值:" prop="value">
<el-input
type="textarea"
:rows="5"
v-model="formData.value"
:clearable="true"
placeholder="请输入参数值"
/>
</el-form-item>
<el-form-item label="参数说明:" prop="desc">
<el-input
v-model="formData.desc"
:clearable="true"
placeholder="请输入参数说明"
/>
</el-form-item>
</el-form>
<div class="usage-instructions bg-gray-100 border border-gray-300 rounded-lg p-4 mt-5">
<div
class="usage-instructions bg-gray-100 border border-gray-300 rounded-lg p-4 mt-5"
>
<h3 class="mb-3 text-lg text-gray-800">使用说明</h3>
<p class="mb-2 text-sm text-gray-600">
前端可以通过引入 <code class="bg-blue-100 px-1 py-0.5 rounded">import { getParams } from '@/utils/dictionary'</code> 然后通过 <code class="bg-blue-100 px-1 py-0.5 rounded">await getParams("{{formData.key}}")</code> 来获取对应的参数。
前端可以通过引入
<code class="bg-blue-100 px-1 py-0.5 rounded"
>import { getParams } from '@/utils/dictionary'</code
>
然后通过
<code class="bg-blue-100 px-1 py-0.5 rounded"
>await getParams("{{ formData.key }}")</code
>
来获取对应的参数。
</p>
<p class="text-sm text-gray-600">
后端需要提前 <code class="bg-blue-100 px-1 py-0.5 rounded">import "github.com/flipped-aurora/gin-vue-admin/server/service/system"</code>
后端需要提前
<code class="bg-blue-100 px-1 py-0.5 rounded"
>import
"github.com/flipped-aurora/gin-vue-admin/server/service/system"</code
>
</p>
<p class="mb-2 text-sm text-gray-600">
然后调用 <code class="bg-blue-100 px-1 py-0.5 rounded">new(system.SysParamsService).GetSysParam("{{formData.key}}")</code> 来获取对应的 value 值。
然后调用
<code class="bg-blue-100 px-1 py-0.5 rounded"
>new(system.SysParamsService).GetSysParam("{{
formData.key
}}")</code
>
来获取对应的 value 值。
</p>
</div>
</el-drawer>
<el-drawer destroy-on-close size="800" v-model="detailShow" :show-close="true" :before-close="closeDetailShow">
<el-descriptions :column="1" border>
<el-descriptions-item label="参数名称">
{{ detailFrom.name }}
</el-descriptions-item>
<el-descriptions-item label="参数键">
{{ detailFrom.key }}
</el-descriptions-item>
<el-descriptions-item label="参数值">
{{ detailFrom.value }}
</el-descriptions-item>
<el-descriptions-item label="参数说明">
{{ detailFrom.desc }}
</el-descriptions-item>
</el-descriptions>
</el-drawer>
<el-drawer
destroy-on-close
size="800"
v-model="detailShow"
:show-close="true"
:before-close="closeDetailShow"
>
<el-descriptions :column="1" border>
<el-descriptions-item label="参数名称">
{{ detailFrom.name }}
</el-descriptions-item>
<el-descriptions-item label="参数键">
{{ detailFrom.key }}
</el-descriptions-item>
<el-descriptions-item label="参数值">
{{ detailFrom.value }}
</el-descriptions-item>
<el-descriptions-item label="参数说明">
{{ detailFrom.desc }}
</el-descriptions-item>
</el-descriptions>
</el-drawer>
</div>
</template>
<script setup>
import {
createSysParams,
deleteSysParams,
deleteSysParamsByIds,
updateSysParams,
findSysParams,
getSysParamsList
} from '@/api/sysParams'
import {
createSysParams,
deleteSysParams,
deleteSysParamsByIds,
updateSysParams,
findSysParams,
getSysParamsList
} from '@/api/sysParams'
// 全量引入格式化工具 请按需保留
import { formatDate } from '@/utils/format'
import { ElMessage, ElMessageBox } from 'element-plus'
import { ref, reactive } from 'vue'
// 全量引入格式化工具 请按需保留
import { formatDate } from '@/utils/format'
import { ElMessage, ElMessageBox } from 'element-plus'
import { ref, reactive } from 'vue'
defineOptions({
defineOptions({
name: 'SysParams'
})
// 控制更多查询条件显示/隐藏状态
const showAllQuery = ref(false)
// 自动化生成的字典(可能为空)以及字段
const formData = ref({
name: '',
key: '',
value: '',
desc: '',
})
// 验证规则
const rule = reactive({
name : [{
required: true,
message: '',
trigger: ['input','blur'],
},
{
whitespace: true,
message: '不能只输入空格',
trigger: ['input', 'blur'],
}
],
key : [{
required: true,
message: '',
trigger: ['input','blur'],
},
{
whitespace: true,
message: '不能只输入空格',
trigger: ['input', 'blur'],
}
],
value : [{
required: true,
message: '',
trigger: ['input','blur'],
},
{
whitespace: true,
message: '不能只输入空格',
trigger: ['input', 'blur'],
}
],
})
const searchRule = reactive({
createdAt: [
{ validator: (rule, value, callback) => {
if (searchInfo.value.startCreatedAt && !searchInfo.value.endCreatedAt) {
callback(new Error('请填写结束日期'))
} else if (!searchInfo.value.startCreatedAt && searchInfo.value.endCreatedAt) {
callback(new Error('请填写开始日期'))
} else if (searchInfo.value.startCreatedAt && searchInfo.value.endCreatedAt && (searchInfo.value.startCreatedAt.getTime() === searchInfo.value.endCreatedAt.getTime() || searchInfo.value.startCreatedAt.getTime() > searchInfo.value.endCreatedAt.getTime())) {
callback(new Error('开始日期应当早于结束日期'))
} else {
callback()
}
}, trigger: 'change' }
],
})
const elFormRef = ref()
const elSearchFormRef = ref()
// =========== 表格控制部分 ===========
const page = ref(1)
const total = ref(0)
const pageSize = ref(10)
const tableData = ref([])
const searchInfo = ref({})
// 重置
const onReset = () => {
searchInfo.value = {}
getTableData()
}
// 搜索
const onSubmit = () => {
elSearchFormRef.value?.validate(async(valid) => {
if (!valid) return
page.value = 1
pageSize.value = 10
getTableData()
})
}
// 分页
const handleSizeChange = (val) => {
pageSize.value = val
getTableData()
}
// 控制更多查询条件显示/隐藏状态
const showAllQuery = ref(false)
// 修改页面容量
const handleCurrentChange = (val) => {
page.value = val
getTableData()
}
// 自动化生成的字典(可能为空)以及字段
const formData = ref({
name: '',
key: '',
value: '',
desc: ''
})
// 查询
const getTableData = async() => {
const table = await getSysParamsList({ page: page.value, pageSize: pageSize.value, ...searchInfo.value })
if (table.code === 0) {
tableData.value = table.data.list
total.value = table.data.total
page.value = table.data.page
pageSize.value = table.data.pageSize
// 验证规则
const rule = reactive({
name: [
{
required: true,
message: '',
trigger: ['input', 'blur']
},
{
whitespace: true,
message: '不能只输入空格',
trigger: ['input', 'blur']
}
],
key: [
{
required: true,
message: '',
trigger: ['input', 'blur']
},
{
whitespace: true,
message: '不能只输入空格',
trigger: ['input', 'blur']
}
],
value: [
{
required: true,
message: '',
trigger: ['input', 'blur']
},
{
whitespace: true,
message: '不能只输入空格',
trigger: ['input', 'blur']
}
]
})
const searchRule = reactive({
createdAt: [
{
validator: (rule, value, callback) => {
if (
searchInfo.value.startCreatedAt &&
!searchInfo.value.endCreatedAt
) {
callback(new Error('请填写结束日期'))
} else if (
!searchInfo.value.startCreatedAt &&
searchInfo.value.endCreatedAt
) {
callback(new Error('请填写开始日期'))
} else if (
searchInfo.value.startCreatedAt &&
searchInfo.value.endCreatedAt &&
(searchInfo.value.startCreatedAt.getTime() ===
searchInfo.value.endCreatedAt.getTime() ||
searchInfo.value.startCreatedAt.getTime() >
searchInfo.value.endCreatedAt.getTime())
) {
callback(new Error('开始日期应当早于结束日期'))
} else {
callback()
}
},
trigger: 'change'
}
]
})
const elFormRef = ref()
const elSearchFormRef = ref()
// =========== 表格控制部分 ===========
const page = ref(1)
const total = ref(0)
const pageSize = ref(10)
const tableData = ref([])
const searchInfo = ref({})
// 重置
const onReset = () => {
searchInfo.value = {}
getTableData()
}
}
getTableData()
// 搜索
const onSubmit = () => {
elSearchFormRef.value?.validate(async (valid) => {
if (!valid) return
page.value = 1
pageSize.value = 10
getTableData()
})
}
// ============== 表格控制部分结束 ===============
// 分页
const handleSizeChange = (val) => {
pageSize.value = val
getTableData()
}
// 获取需要的字典 可能为空 按需保留
const setOptions = async () =>{
}
// 修改页面容量
const handleCurrentChange = (val) => {
page.value = val
getTableData()
}
// 获取需要的字典 可能为空 按需保留
setOptions()
// 多选数据
const multipleSelection = ref([])
// 多选
const handleSelectionChange = (val) => {
multipleSelection.value = val
}
// 删除行
const deleteRow = (row) => {
ElMessageBox.confirm('确定要删除吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
deleteSysParamsFunc(row)
})
// 查询
const getTableData = async () => {
const table = await getSysParamsList({
page: page.value,
pageSize: pageSize.value,
...searchInfo.value
})
if (table.code === 0) {
tableData.value = table.data.list
total.value = table.data.total
page.value = table.data.page
pageSize.value = table.data.pageSize
}
}
// 多选删除
const onDelete = async() => {
ElMessageBox.confirm('确定要删除吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(async() => {
getTableData()
// ============== 表格控制部分结束 ===============
// 获取需要的字典 可能为空 按需保留
const setOptions = async () => {}
// 获取需要的字典 可能为空 按需保留
setOptions()
// 多选数据
const multipleSelection = ref([])
// 多选
const handleSelectionChange = (val) => {
multipleSelection.value = val
}
// 删除行
const deleteRow = (row) => {
ElMessageBox.confirm('确定要删除吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
deleteSysParamsFunc(row)
})
}
// 多选删除
const onDelete = async () => {
ElMessageBox.confirm('确定要删除吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(async () => {
const IDs = []
if (multipleSelection.value.length === 0) {
ElMessage({
@@ -324,7 +482,7 @@ const onDelete = async() => {
return
}
multipleSelection.value &&
multipleSelection.value.map(item => {
multipleSelection.value.map((item) => {
IDs.push(item.ID)
})
const res = await deleteSysParamsByIds({ IDs })
@@ -338,117 +496,108 @@ const onDelete = async() => {
}
getTableData()
}
})
}
})
}
// 行为控制标记(弹窗内部需要增还是改)
const type = ref('')
// 行为控制标记(弹窗内部需要增还是改)
const type = ref('')
// 更新行
const updateSysParamsFunc = async(row) => {
// 更新行
const updateSysParamsFunc = async (row) => {
const res = await findSysParams({ ID: row.ID })
type.value = 'update'
if (res.code === 0) {
formData.value = res.data
dialogFormVisible.value = true
formData.value = res.data
dialogFormVisible.value = true
}
}
}
// 删除行
const deleteSysParamsFunc = async (row) => {
// 删除行
const deleteSysParamsFunc = async (row) => {
const res = await deleteSysParams({ ID: row.ID })
if (res.code === 0) {
ElMessage({
type: 'success',
message: '删除成功'
})
if (tableData.value.length === 1 && page.value > 1) {
page.value--
}
getTableData()
ElMessage({
type: 'success',
message: '删除成功'
})
if (tableData.value.length === 1 && page.value > 1) {
page.value--
}
getTableData()
}
}
}
// 弹窗控制标记
const dialogFormVisible = ref(false)
// 弹窗控制标记
const dialogFormVisible = ref(false)
// 打开弹窗
const openDialog = () => {
// 打开弹窗
const openDialog = () => {
type.value = 'create'
dialogFormVisible.value = true
}
}
// 关闭弹窗
const closeDialog = () => {
// 关闭弹窗
const closeDialog = () => {
dialogFormVisible.value = false
formData.value = {
name: '',
key: '',
value: '',
desc: '',
}
}
// 弹窗确定
const enterDialog = async () => {
elFormRef.value?.validate( async (valid) => {
if (!valid) return
let res
switch (type.value) {
case 'create':
res = await createSysParams(formData.value)
break
case 'update':
res = await updateSysParams(formData.value)
break
default:
res = await createSysParams(formData.value)
break
}
if (res.code === 0) {
ElMessage({
type: 'success',
message: '创建/更改成功'
})
closeDialog()
getTableData()
}
})
}
const detailFrom = ref({})
// 查看详情控制标记
const detailShow = ref(false)
// 打开详情弹窗
const openDetailShow = () => {
detailShow.value = true
}
// 打开详情
const getDetails = async (row) => {
// 打开弹窗
const res = await findSysParams({ ID: row.ID })
if (res.code === 0) {
detailFrom.value = res.data
openDetailShow()
name: '',
key: '',
value: '',
desc: ''
}
}
// 弹窗确定
const enterDialog = async () => {
elFormRef.value?.validate(async (valid) => {
if (!valid) return
let res
switch (type.value) {
case 'create':
res = await createSysParams(formData.value)
break
case 'update':
res = await updateSysParams(formData.value)
break
default:
res = await createSysParams(formData.value)
break
}
if (res.code === 0) {
ElMessage({
type: 'success',
message: '创建/更改成功'
})
closeDialog()
getTableData()
}
})
}
}
const detailFrom = ref({})
// 关闭详情弹窗
const closeDetailShow = () => {
detailShow.value = false
detailFrom.value = {}
}
// 查看详情控制标记
const detailShow = ref(false)
// 打开详情弹窗
const openDetailShow = () => {
detailShow.value = true
}
// 打开详情
const getDetails = async (row) => {
// 打开弹窗
const res = await findSysParams({ ID: row.ID })
if (res.code === 0) {
detailFrom.value = res.data
openDetailShow()
}
}
// 关闭详情弹窗
const closeDetailShow = () => {
detailShow.value = false
detailFrom.value = {}
}
</script>
<style>
</style>
<style></style>
+333 -371
View File
@@ -2,82 +2,40 @@
<div>
<warning-bar title="注:右上角头像下拉可切换角色" />
<div class="gva-search-box">
<el-form
ref="searchForm"
:inline="true"
:model="searchInfo"
>
<el-form ref="searchForm" :inline="true" :model="searchInfo">
<el-form-item label="用户名">
<el-input
v-model="searchInfo.username"
placeholder="用户名"
/>
<el-input v-model="searchInfo.username" placeholder="用户名" />
</el-form-item>
<el-form-item label="昵称">
<el-input
v-model="searchInfo.nickname"
placeholder="昵称"
/>
<el-input v-model="searchInfo.nickname" placeholder="昵称" />
</el-form-item>
<el-form-item label="手机号">
<el-input
v-model="searchInfo.phone"
placeholder="手机号"
/>
<el-input v-model="searchInfo.phone" placeholder="手机号" />
</el-form-item>
<el-form-item label="邮箱">
<el-input
v-model="searchInfo.email"
placeholder="邮箱"
/>
<el-input v-model="searchInfo.email" placeholder="邮箱" />
</el-form-item>
<el-form-item>
<el-button
type="primary"
icon="search"
@click="onSubmit"
>
<el-button type="primary" icon="search" @click="onSubmit">
查询
</el-button>
<el-button
icon="refresh"
@click="onReset"
>
重置
</el-button>
<el-button icon="refresh" @click="onReset"> 重置 </el-button>
</el-form-item>
</el-form>
</div>
<div class="gva-table-box">
<div class="gva-btn-list">
<el-button
type="primary"
icon="plus"
@click="addUser"
>新增用户</el-button>
</div>
<el-table
:data="tableData"
row-key="ID"
>
<el-table-column
align="left"
label="头像"
min-width="75"
<el-button type="primary" icon="plus" @click="addUser"
>新增用户</el-button
>
</div>
<el-table :data="tableData" row-key="ID">
<el-table-column align="left" label="头像" min-width="75">
<template #default="scope">
<CustomPic
style="margin-top:8px"
:pic-src="scope.row.headerImg"
/>
<CustomPic style="margin-top: 8px" :pic-src="scope.row.headerImg" />
</template>
</el-table-column>
<el-table-column
align="left"
label="ID"
min-width="50"
prop="ID"
/>
<el-table-column align="left" label="ID" min-width="50" prop="ID" />
<el-table-column
align="left"
label="用户名"
@@ -102,67 +60,76 @@
min-width="180"
prop="email"
/>
<el-table-column
align="left"
label="用户角色"
min-width="200"
>
<el-table-column align="left" label="用户角色" min-width="200">
<template #default="scope">
<el-cascader
v-model="scope.row.authorityIds"
:options="authOptions"
:show-all-levels="false"
collapse-tags
:props="{ multiple:true,checkStrictly: true,label:'authorityName',value:'authorityId',disabled:'disabled',emitPath:false}"
:props="{
multiple: true,
checkStrictly: true,
label: 'authorityName',
value: 'authorityId',
disabled: 'disabled',
emitPath: false
}"
:clearable="false"
@visible-change="(flag)=>{changeAuthority(scope.row,flag,0)}"
@remove-tag="(removeAuth)=>{changeAuthority(scope.row,false,removeAuth)}"
@visible-change="
(flag) => {
changeAuthority(scope.row, flag, 0)
}
"
@remove-tag="
(removeAuth) => {
changeAuthority(scope.row, false, removeAuth)
}
"
/>
</template>
</el-table-column>
<el-table-column
align="left"
label="启用"
min-width="150"
>
<el-table-column align="left" label="启用" min-width="150">
<template #default="scope">
<el-switch
v-model="scope.row.enable"
inline-prompt
:active-value="1"
:inactive-value="2"
@change="()=>{switchEnable(scope.row)}"
@change="
() => {
switchEnable(scope.row)
}
"
/>
</template>
</el-table-column>
<el-table-column
label="操作"
min-width="250"
fixed="right"
>
<el-table-column label="操作" min-width="250" fixed="right">
<template #default="scope">
<el-button
type="primary"
link
icon="delete"
@click="deleteUserFunc(scope.row)"
>删除</el-button>
>删除</el-button
>
<el-button
type="primary"
link
icon="edit"
@click="openEdit(scope.row)"
>编辑</el-button>
>编辑</el-button
>
<el-button
type="primary"
link
icon="magic-stick"
@click="resetPasswordFunc(scope.row)"
>重置密码</el-button>
>重置密码</el-button
>
</template>
</el-table-column>
</el-table>
<div class="gva-pagination">
<el-pagination
@@ -188,10 +155,9 @@
<span class="text-lg">用户</span>
<div>
<el-button @click="closeAddUserDialog">取 消</el-button>
<el-button
type="primary"
@click="enterAddUserDialog"
>确 定</el-button>
<el-button type="primary" @click="enterAddUserDialog"
>确 定</el-button
>
</div>
</div>
</template>
@@ -209,48 +175,36 @@
>
<el-input v-model="userInfo.userName" />
</el-form-item>
<el-form-item
v-if="dialogFlag === 'add'"
label="密码"
prop="password"
>
<el-form-item v-if="dialogFlag === 'add'" label="密码" prop="password">
<el-input v-model="userInfo.password" />
</el-form-item>
<el-form-item
label="昵称"
prop="nickName"
>
<el-form-item label="昵称" prop="nickName">
<el-input v-model="userInfo.nickName" />
</el-form-item>
<el-form-item
label="手机号"
prop="phone"
>
<el-form-item label="手机号" prop="phone">
<el-input v-model="userInfo.phone" />
</el-form-item>
<el-form-item
label="邮箱"
prop="email"
>
<el-form-item label="邮箱" prop="email">
<el-input v-model="userInfo.email" />
</el-form-item>
<el-form-item
label="用户角色"
prop="authorityId"
>
<el-form-item label="用户角色" prop="authorityId">
<el-cascader
v-model="userInfo.authorityIds"
style="width:100%"
style="width: 100%"
:options="authOptions"
:show-all-levels="false"
:props="{ multiple:true,checkStrictly: true,label:'authorityName',value:'authorityId',disabled:'disabled',emitPath:false}"
:props="{
multiple: true,
checkStrictly: true,
label: 'authorityName',
value: 'authorityId',
disabled: 'disabled',
emitPath: false
}"
:clearable="false"
/>
</el-form-item>
<el-form-item
label="启用"
prop="disabled"
>
<el-form-item label="启用" prop="disabled">
<el-switch
v-model="userInfo.enable"
inline-prompt
@@ -258,13 +212,8 @@
:inactive-value="2"
/>
</el-form-item>
<el-form-item
label="头像"
label-width="80px"
>
<SelectImage
v-model="userInfo.headerImg"
/>
<el-form-item label="头像" label-width="80px">
<SelectImage v-model="userInfo.headerImg" />
</el-form-item>
</el-form>
</el-drawer>
@@ -272,288 +221,301 @@
</template>
<script setup>
import {
getUserList,
setUserAuthorities,
register,
deleteUser
} from '@/api/user'
import {
getUserList,
setUserAuthorities,
register,
deleteUser
} from '@/api/user'
import { getAuthorityList } from '@/api/authority'
import CustomPic from '@/components/customPic/index.vue'
import WarningBar from '@/components/warningBar/warningBar.vue'
import { setUserInfo, resetPassword } from '@/api/user.js'
import { getAuthorityList } from '@/api/authority'
import CustomPic from '@/components/customPic/index.vue'
import WarningBar from '@/components/warningBar/warningBar.vue'
import { setUserInfo, resetPassword } from '@/api/user.js'
import { nextTick, ref, watch } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import SelectImage from '@/components/selectImage/selectImage.vue'
import { nextTick, ref, watch } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import SelectImage from '@/components/selectImage/selectImage.vue'
defineOptions({
name: 'User'
})
defineOptions({
name: 'User',
})
const searchInfo = ref({
username: '',
nickname: '',
phone: '',
email: ''
})
const onSubmit = () => {
page.value = 1
getTableData()
}
const onReset = () => {
searchInfo.value = {
const searchInfo = ref({
username: '',
nickname: '',
phone: '',
email: ''
})
const onSubmit = () => {
page.value = 1
getTableData()
}
getTableData()
}
// 初始化相关
const setAuthorityOptions = (AuthorityData, optionsData) => {
AuthorityData &&
AuthorityData.forEach(item => {
if (item.children && item.children.length) {
const option = {
authorityId: item.authorityId,
authorityName: item.authorityName,
children: []
}
setAuthorityOptions(item.children, option.children)
optionsData.push(option)
} else {
const option = {
authorityId: item.authorityId,
authorityName: item.authorityName
}
optionsData.push(option)
const onReset = () => {
searchInfo.value = {
username: '',
nickname: '',
phone: '',
email: ''
}
getTableData()
}
// 初始化相关
const setAuthorityOptions = (AuthorityData, optionsData) => {
AuthorityData &&
AuthorityData.forEach((item) => {
if (item.children && item.children.length) {
const option = {
authorityId: item.authorityId,
authorityName: item.authorityName,
children: []
}
})
}
const page = ref(1)
const total = ref(0)
const pageSize = ref(10)
const tableData = ref([])
// 分页
const handleSizeChange = (val) => {
pageSize.value = val
getTableData()
}
const handleCurrentChange = (val) => {
page.value = val
getTableData()
}
// 查询
const getTableData = async() => {
const table = await getUserList({ page: page.value, pageSize: pageSize.value, ...searchInfo.value })
if (table.code === 0) {
tableData.value = table.data.list
total.value = table.data.total
page.value = table.data.page
pageSize.value = table.data.pageSize
setAuthorityOptions(item.children, option.children)
optionsData.push(option)
} else {
const option = {
authorityId: item.authorityId,
authorityName: item.authorityName
}
optionsData.push(option)
}
})
}
}
watch(() => tableData.value, () => {
setAuthorityIds()
})
const page = ref(1)
const total = ref(0)
const pageSize = ref(10)
const tableData = ref([])
// 分页
const handleSizeChange = (val) => {
pageSize.value = val
getTableData()
}
const initPage = async() => {
getTableData()
const res = await getAuthorityList()
setOptions(res.data)
}
const handleCurrentChange = (val) => {
page.value = val
getTableData()
}
initPage()
// 查询
const getTableData = async () => {
const table = await getUserList({
page: page.value,
pageSize: pageSize.value,
...searchInfo.value
})
if (table.code === 0) {
tableData.value = table.data.list
total.value = table.data.total
page.value = table.data.page
pageSize.value = table.data.pageSize
}
}
const resetPasswordFunc = (row) => {
ElMessageBox.confirm(
'是否将此用户密码重置为123456?',
'警告',
{
watch(
() => tableData.value,
() => {
setAuthorityIds()
}
)
const initPage = async () => {
getTableData()
const res = await getAuthorityList()
setOptions(res.data)
}
initPage()
const resetPasswordFunc = (row) => {
ElMessageBox.confirm('是否将此用户密码重置为123456?', '警告', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}
).then(async() => {
const res = await resetPassword({
ID: row.ID,
type: 'warning'
}).then(async () => {
const res = await resetPassword({
ID: row.ID
})
if (res.code === 0) {
ElMessage({
type: 'success',
message: res.msg
})
} else {
ElMessage({
type: 'error',
message: res.msg
})
}
})
}
const setAuthorityIds = () => {
tableData.value &&
tableData.value.forEach((user) => {
user.authorityIds =
user.authorities &&
user.authorities.map((i) => {
return i.authorityId
})
})
}
const authOptions = ref([])
const setOptions = (authData) => {
authOptions.value = []
setAuthorityOptions(authData, authOptions.value)
}
const deleteUserFunc = async (row) => {
ElMessageBox.confirm('确定要删除吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(async () => {
const res = await deleteUser({ id: row.ID })
if (res.code === 0) {
ElMessage.success('删除成功')
await getTableData()
}
})
}
// 弹窗相关
const userInfo = ref({
userName: '',
password: '',
nickName: '',
headerImg: '',
authorityId: '',
authorityIds: [],
enable: 1
})
const rules = ref({
userName: [
{ required: true, message: '请输入用户名', trigger: 'blur' },
{ min: 5, message: '最低5位字符', trigger: 'blur' }
],
password: [
{ required: true, message: '请输入用户密码', trigger: 'blur' },
{ min: 6, message: '最低6位字符', trigger: 'blur' }
],
nickName: [{ required: true, message: '请输入用户昵称', trigger: 'blur' }],
phone: [
{
pattern: /^1([38][0-9]|4[014-9]|[59][0-35-9]|6[2567]|7[0-8])\d{8}$/,
message: '请输入合法手机号',
trigger: 'blur'
}
],
email: [
{
pattern: /^([0-9A-Za-z\-_.]+)@([0-9a-z]+\.[a-z]{2,3}(\.[a-z]{2})?)$/g,
message: '请输入正确的邮箱',
trigger: 'blur'
}
],
authorityId: [
{ required: true, message: '请选择用户角色', trigger: 'blur' }
]
})
const userForm = ref(null)
const enterAddUserDialog = async () => {
userInfo.value.authorityId = userInfo.value.authorityIds[0]
userForm.value.validate(async (valid) => {
if (valid) {
const req = {
...userInfo.value
}
if (dialogFlag.value === 'add') {
const res = await register(req)
if (res.code === 0) {
ElMessage({ type: 'success', message: '创建成功' })
await getTableData()
closeAddUserDialog()
}
}
if (dialogFlag.value === 'edit') {
const res = await setUserInfo(req)
if (res.code === 0) {
ElMessage({ type: 'success', message: '编辑成功' })
await getTableData()
closeAddUserDialog()
}
}
}
})
}
const addUserDialog = ref(false)
const closeAddUserDialog = () => {
userForm.value.resetFields()
userInfo.value.headerImg = ''
userInfo.value.authorityIds = []
addUserDialog.value = false
}
const dialogFlag = ref('add')
const addUser = () => {
dialogFlag.value = 'add'
addUserDialog.value = true
}
const tempAuth = {}
const changeAuthority = async (row, flag, removeAuth) => {
if (flag) {
if (!removeAuth) {
tempAuth[row.ID] = [...row.authorityIds]
}
return
}
await nextTick()
const res = await setUserAuthorities({
ID: row.ID,
authorityIds: row.authorityIds
})
if (res.code === 0) {
ElMessage({ type: 'success', message: '角色设置成功' })
} else {
if (!removeAuth) {
row.authorityIds = [...tempAuth[row.ID]]
delete tempAuth[row.ID]
} else {
row.authorityIds = [removeAuth, ...row.authorityIds]
}
}
}
const openEdit = (row) => {
dialogFlag.value = 'edit'
userInfo.value = JSON.parse(JSON.stringify(row))
addUserDialog.value = true
}
const switchEnable = async (row) => {
userInfo.value = JSON.parse(JSON.stringify(row))
await nextTick()
const req = {
...userInfo.value
}
const res = await setUserInfo(req)
if (res.code === 0) {
ElMessage({
type: 'success',
message: res.msg,
message: `${req.enable === 2 ? '禁用' : '启用'}成功`
})
} else {
ElMessage({
type: 'error',
message: res.msg,
})
}
})
}
const setAuthorityIds = () => {
tableData.value && tableData.value.forEach((user) => {
user.authorityIds = user.authorities && user.authorities.map(i => {
return i.authorityId
})
})
}
const authOptions = ref([])
const setOptions = (authData) => {
authOptions.value = []
setAuthorityOptions(authData, authOptions.value)
}
const deleteUserFunc = async(row) => {
ElMessageBox.confirm('确定要删除吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(async() => {
const res = await deleteUser({ id: row.ID })
if (res.code === 0) {
ElMessage.success('删除成功')
await getTableData()
}
})
}
// 弹窗相关
const userInfo = ref({
userName: '',
password: '',
nickName: '',
headerImg: '',
authorityId: '',
authorityIds: [],
enable: 1,
})
const rules = ref({
userName: [
{ required: true, message: '请输入用户名', trigger: 'blur' },
{ min: 5, message: '最低5位字符', trigger: 'blur' }
],
password: [
{ required: true, message: '请输入用户密码', trigger: 'blur' },
{ min: 6, message: '最低6位字符', trigger: 'blur' }
],
nickName: [
{ required: true, message: '请输入用户昵称', trigger: 'blur' }
],
phone: [
{ pattern: /^1([38][0-9]|4[014-9]|[59][0-35-9]|6[2567]|7[0-8])\d{8}$/, message: '请输入合法手机号', trigger: 'blur' },
],
email: [
{ pattern: /^([0-9A-Za-z\-_.]+)@([0-9a-z]+\.[a-z]{2,3}(\.[a-z]{2})?)$/g, message: '请输入正确的邮箱', trigger: 'blur' },
],
authorityId: [
{ required: true, message: '请选择用户角色', trigger: 'blur' }
]
})
const userForm = ref(null)
const enterAddUserDialog = async() => {
userInfo.value.authorityId = userInfo.value.authorityIds[0]
userForm.value.validate(async valid => {
if (valid) {
const req = {
...userInfo.value
}
if (dialogFlag.value === 'add') {
const res = await register(req)
if (res.code === 0) {
ElMessage({ type: 'success', message: '创建成功' })
await getTableData()
closeAddUserDialog()
}
}
if (dialogFlag.value === 'edit') {
const res = await setUserInfo(req)
if (res.code === 0) {
ElMessage({ type: 'success', message: '编辑成功' })
await getTableData()
closeAddUserDialog()
}
}
}
})
}
const addUserDialog = ref(false)
const closeAddUserDialog = () => {
userForm.value.resetFields()
userInfo.value.headerImg = ''
userInfo.value.authorityIds = []
addUserDialog.value = false
}
const dialogFlag = ref('add')
const addUser = () => {
dialogFlag.value = 'add'
addUserDialog.value = true
}
const tempAuth = {}
const changeAuthority = async(row, flag, removeAuth) => {
if (flag) {
if (!removeAuth) {
tempAuth[row.ID] = [...row.authorityIds]
}
return
}
await nextTick()
const res = await setUserAuthorities({
ID: row.ID,
authorityIds: row.authorityIds
})
if (res.code === 0) {
ElMessage({ type: 'success', message: '角色设置成功' })
} else {
if (!removeAuth) {
row.authorityIds = [...tempAuth[row.ID]]
delete tempAuth[row.ID]
} else {
row.authorityIds = [removeAuth, ...row.authorityIds]
userInfo.value.headerImg = ''
userInfo.value.authorityIds = []
}
}
}
const openEdit = (row) => {
dialogFlag.value = 'edit'
userInfo.value = JSON.parse(JSON.stringify(row))
addUserDialog.value = true
}
const switchEnable = async(row) => {
userInfo.value = JSON.parse(JSON.stringify(row))
await nextTick()
const req = {
...userInfo.value
}
const res = await setUserInfo(req)
if (res.code === 0) {
ElMessage({ type: 'success', message: `${req.enable === 2 ? '禁用' : '启用'}成功` })
await getTableData()
userInfo.value.headerImg = ''
userInfo.value.authorityIds = []
}
}
</script>
<style lang="scss">
.header-img-box {
@apply w-52 h-52 border border-solid border-gray-300 rounded-xl flex justify-center items-center cursor-pointer;
}
}
</style>