搜索
重置
@@ -72,9 +72,9 @@
-
+
-
+
diff --git a/src/views/api/PhotoWall.vue b/src/views/api/PhotoWall.vue
index 34554a2..e093a27 100644
--- a/src/views/api/PhotoWall.vue
+++ b/src/views/api/PhotoWall.vue
@@ -41,9 +41,9 @@
auto-upload
:show-file-list="false"
style="display: inline-block;margin-right: 10px;">
-
上传图片
+
上传图片
-
批量删除
+
批量删除
搜索
重置
diff --git a/src/views/api/SourceImage.vue b/src/views/api/SourceImage.vue
index 9beb327..a880bff 100644
--- a/src/views/api/SourceImage.vue
+++ b/src/views/api/SourceImage.vue
@@ -16,9 +16,9 @@
auto-upload
:show-file-list="false"
style="display: inline-block;margin-right: 10px;">
- 上传图片
+ 上传图片
- 批量删除
+ 批量删除
@@ -41,7 +41,7 @@
-
+
diff --git a/src/views/system/Article.vue b/src/views/system/Article.vue
index 1d73a8c..f058586 100644
--- a/src/views/system/Article.vue
+++ b/src/views/system/Article.vue
@@ -30,8 +30,8 @@
-
分词处理
-
拉取文章
+
分词处理
+
拉取文章
+ style="display: inline-block;margin-left: 10px;"
+ v-permission="'system:deploy'">
发布博客
diff --git a/src/views/system/SystemConfig.vue b/src/views/system/SystemConfig.vue
index f2d86a6..e98b3e3 100644
--- a/src/views/system/SystemConfig.vue
+++ b/src/views/system/SystemConfig.vue
@@ -6,7 +6,7 @@
-
添加
+
添加
搜索
重置
@@ -37,8 +37,8 @@
-
-
+
+
diff --git a/src/views/system/SystemRole.vue b/src/views/system/SystemRole.vue
index 37158bf..e628a18 100644
--- a/src/views/system/SystemRole.vue
+++ b/src/views/system/SystemRole.vue
@@ -6,7 +6,7 @@
-
添加
+
添加
搜索
重置
@@ -14,11 +14,7 @@
-
-
- {{method}}
-
-
+
{{ datetimeFormat(scope.row.createdAt) }}
@@ -31,8 +27,8 @@
-
-
+
+
@@ -54,29 +50,17 @@
-
-
- GET
- POST
- PUT
- DELETE
-
-
-
-
-
-
-
-
- {{uri}}
-
-
-
-
-
-
-
- {{uri}}
+
+
@@ -95,9 +79,9 @@ import { useStore } from 'vuex'
import { useBaseList } from '@/model/baselist'
import { Page } from '@/model/common.dto'
import http from '@/utils/http'
-import { SystemRoleModel } from '@/model/system/system-role'
+import { SystemRoleModel, PermissionTreeNode } from '@/model/system/system-role'
import { ElMessage, ElMessageBox } from 'element-plus'
-import { VForm } from '@/types'
+import type { VForm } from '@/types'
const store = useStore()
@@ -115,26 +99,33 @@ const ruleValidate = {
name: [
{ required: true, message: '请输入角色名称', trigger: 'blur' }
],
+ permissions: [
+ { validator: (rule: any, value: any, callback: any) => {
+ const permissions = getPermissionsToSave()
+ if (permissions.length === 0) {
+ callback(new Error('至少需要勾选一项权限'))
+ } else {
+ callback()
+ }
+ }, trigger: 'change' }
+ ]
}
const systemRoleData = ref([])
const addModal = ref(false)
const modalTitle = ref(null)
-const uri = reactive<{
- include: string | null,
- exclude: string | null
-}>({
- include: null,
- exclude: null
-})
+const permissionTreeData = ref([])
+const treeProps = {
+ children: 'children',
+ label: 'name'
+}
const formData = reactive({
_id: null,
name: null,
description: null,
- methods: [],
- includeUri: [],
- excludeUri: []
+ permissions: []
})
const roleForm = ref()
+const permTree = ref()
async function loadData() {
loading.value = true
@@ -146,49 +137,142 @@ async function loadData() {
setLoadData(loadData)
function add() {
- uri.include = null
- uri.exclude = null
Object.assign(formData, {
_id: null,
name: null,
description: null,
- methods: [],
- includeUri: [],
- excludeUri: []
+ permissions: []
})
modalTitle.value = '新增角色'
addModal.value = true
clearValidate()
+ nextTick(() => {
+ permTree.value?.setCheckedKeys([])
+ })
}
-function addUri(fieldName: 'includeUri' | 'excludeUri', uriValue: string | null) {
- if(!uriValue) return
- if(formData[fieldName].indexOf(uriValue) === -1) {
- formData[fieldName].push(uriValue)
+/**
+ * 处理权限树勾选:
+ * - 勾选父节点时,自动勾选所有子节点
+ * - 取消父节点时,自动取消所有子节点
+ * - 所有子节点都被勾选时,自动勾选父节点并取消子节点勾选(只保留父code)
+ */
+function handlePermCheck(nodeData: PermissionTreeNode, checkState: { checkedKeys: string[], halfCheckedKeys: string[] }) {
+ const tree = permTree.value
+ if (!tree) return
+ const node = tree.getNode(nodeData.code)
+ const isChecked = node.checked
+
+ if (!nodeData.leaf) {
+ // 父节点操作:联动所有子节点
+ const childCodes = nodeData.children.map((c: PermissionTreeNode) => c.code)
+ if (isChecked) {
+ // 勾选父节点 → 勾选所有子节点
+ childCodes.forEach((code: string) => tree.setChecked(code, true, false))
+ } else {
+ // 取消父节点 → 取消所有子节点
+ childCodes.forEach((code: string) => tree.setChecked(code, false, false))
+ }
+ } else {
+ // 子节点操作:检查是否所有兄弟节点都被勾选
+ const parentNode = findParentNode(permissionTreeData.value, nodeData.code)
+ if (parentNode) {
+ const allChildCodes = parentNode.children.map(c => c.code)
+ const allChecked = allChildCodes.every(code => tree.getNode(code)?.checked)
+ if (allChecked) {
+ // 所有子节点勾选 → 勾选父节点
+ tree.setChecked(parentNode.code, true, false)
+ } else {
+ // 不是全部 → 取消父节点
+ tree.setChecked(parentNode.code, false, false)
+ }
+ }
}
}
-function removeUri(fieldName: 'includeUri' | 'excludeUri', uriValue: string) {
- let index = formData[fieldName].indexOf(uriValue)
- if(index !== -1) {
- formData[fieldName].splice(index, 1)
+function handlePermCheckWithValidate(nodeData: PermissionTreeNode, checkState: { checkedKeys: string[], halfCheckedKeys: string[] }) {
+ handlePermCheck(nodeData, checkState)
+ roleForm.value?.validateField('permissions')
+}
+
+function findParentNode(nodes: PermissionTreeNode[], childCode: string): PermissionTreeNode | null {
+ for (const node of nodes) {
+ if (node.children.some(c => c.code === childCode)) {
+ return node
+ }
+ const found = findParentNode(node.children, childCode)
+ if (found) return found
}
+ return null
+}
+
+/**
+ * 从树中获取要保存的 permissions:
+ * 如果父节点被勾选,只传父节点code;否则传各个被勾选的子节点code
+ */
+function getPermissionsToSave(): string[] {
+ const tree = permTree.value
+ if (!tree) return []
+ const result: string[] = []
+ for (const group of permissionTreeData.value) {
+ const parentNode = tree.getNode(group.code)
+ if (parentNode?.checked) {
+ result.push(group.code)
+ } else {
+ for (const child of group.children) {
+ const childNode = tree.getNode(child.code)
+ if (childNode?.checked) {
+ result.push(child.code)
+ }
+ }
+ }
+ }
+ return result
+}
+
+/**
+ * 编辑角色时,根据已有 permissions 回显树的勾选状态
+ * 如果有父级code(如'user'),需要勾选父节点及所有子节点
+ */
+function setTreeCheckedByPermissions(permissions: string[]) {
+ nextTick(() => {
+ const tree = permTree.value
+ if (!tree) return
+ tree.setCheckedKeys([])
+ for (const perm of permissions) {
+ // 查找是否是父节点
+ const parentGroup = permissionTreeData.value.find(g => g.code === perm)
+ if (parentGroup) {
+ // 是父节点:勾选自身和所有子节点
+ tree.setChecked(perm, true, false)
+ parentGroup.children.forEach(c => tree.setChecked(c.code, true, false))
+ } else {
+ tree.setChecked(perm, true, false)
+ }
+ }
+ // 再次检查:如果某个父级的所有子节点都勾选了,勾选父级
+ for (const group of permissionTreeData.value) {
+ if (!permissions.includes(group.code)) {
+ const allChildChecked = group.children.length > 0 && group.children.every(c => tree.getNode(c.code)?.checked)
+ if (allChildChecked) {
+ tree.setChecked(group.code, true, false)
+ }
+ }
+ }
+ })
}
function update(row: SystemRoleModel) {
- uri.include = null
- uri.exclude = null
Object.assign(formData, {
_id: row._id,
name: row.name,
description: row.description,
- methods: row.methods,
- includeUri: row.includeUri,
- excludeUri: row.excludeUri
+ permissions: [...row.permissions]
})
modalTitle.value = '修改角色'
addModal.value = true
clearValidate()
+ setTreeCheckedByPermissions(row.permissions)
}
function remove(row: SystemRoleModel) {
@@ -203,7 +287,8 @@ async function save() {
roleForm.value?.validate(async (valid: boolean) => {
if (!valid) return
modalLoading.value = true
- await http.post('/system/role/save', formData)
+ const saveData = { ...formData, permissions: getPermissionsToSave() }
+ await http.post('/system/role/save', saveData)
modalLoading.value = false
addModal.value = false
ElMessage.success("保存成功")
@@ -218,4 +303,7 @@ function clearValidate() {
}
loadData()
+http.get('/system/role/permissionTree').then(data => {
+ permissionTreeData.value = data
+})
\ No newline at end of file
diff --git a/src/views/system/SystemUser.vue b/src/views/system/SystemUser.vue
index 4b580cb..bf58750 100644
--- a/src/views/system/SystemUser.vue
+++ b/src/views/system/SystemUser.vue
@@ -6,7 +6,7 @@
-
添加
+
添加
搜索
重置
@@ -27,8 +27,8 @@
-
-
+
+