From 1e4a145667f460778560defccab1137b84139985 Mon Sep 17 00:00:00 2001 From: yinbangzhong <zhongbangyin@126.com> Date: 星期一, 29 七月 2024 14:10:16 +0800 Subject: [PATCH] 权限资源 --- src/locale/en-US.ts | 2 src/views/authority/resource/locale/en-US.ts | 5 src/views/authority/resource/locale/zh-CN.ts | 4 src/locale/zh-CN.ts | 2 src/api/authority.ts | 43 +++++++ src/api/user.ts | 3 src/router/routes/modules/authority.ts | 10 + src/views/authority/organization/index.vue | 6 + src/views/authority/resource/index.vue | 248 +++++++++++++++++++++++++++++++++++++++++ 9 files changed, 322 insertions(+), 1 deletions(-) diff --git a/src/api/authority.ts b/src/api/authority.ts index 0e4e193..e322a2e 100644 --- a/src/api/authority.ts +++ b/src/api/authority.ts @@ -25,6 +25,26 @@ parentName: string; } +export interface Resource { + "menuId": string; + "createTime": string; + "updateTime": string; + "menuName": string; + "component": string; + "description": string; + "icon": string; + "orderNum": string; + "target": string; + "parentId": string; + "parentName":string; + "children": any; + "syesourcetype": string; + "status": string; + "path": string; + "perms": string; + "menuType": string; +} + export interface Result<T> { code: number; msg: string; @@ -77,4 +97,27 @@ export function OrganizationById(id) { return axios.get<Result<Organization>>("/base/system/dept/" + id); +} + + +export function ResourceList(key: string) { + return axios.get<Result<Resource[]>>("/base/system/menu/treeselect"); +} + + +export function ResourceAdd(resource) { + return axios.post("/base/system/menu", { resource }); +} + +export function ResourceDelete(id) { + return axios.delete("/base/system/menu/" + id); +} + +export function ResourceUpdate(resource) { + return axios.put("/base/system/menu", { resource }); +} + + +export function ResourceById(id) { + return axios.get<Result<Resource>>("/base/system/menu/" + id); } \ No newline at end of file diff --git a/src/api/user.ts b/src/api/user.ts index d77dd4a..498bf1b 100644 --- a/src/api/user.ts +++ b/src/api/user.ts @@ -11,7 +11,8 @@ token: string; } export function login(data: LoginData) { - return axios.post<LoginRes>('/v1/user/login', data); + // return axios.post<LoginRes>('/v1/user/login', data); + return axios.post<LoginRes>('/base/login', data); } export function logout() { diff --git a/src/locale/en-US.ts b/src/locale/en-US.ts index 27a2b4d..a367da7 100644 --- a/src/locale/en-US.ts +++ b/src/locale/en-US.ts @@ -5,6 +5,7 @@ import localeUser from '@/views/authority/users/locale/en-US'; import localeOrganization from '@/views/authority/organization/locale/en-US'; +import localeResource from '@/views/authority/resource/locale/en-US'; import localeMonitor from '@/views/dashboard/monitor/locale/en-US'; @@ -57,6 +58,7 @@ ...localeUser, ...localeOrganization, + ...localeResource, ...localeMonitor, ...localeSearchTable, diff --git a/src/locale/zh-CN.ts b/src/locale/zh-CN.ts index 02747ec..727b363 100644 --- a/src/locale/zh-CN.ts +++ b/src/locale/zh-CN.ts @@ -5,6 +5,7 @@ import localeUser from '@/views/authority/users/locale/zh-CN'; import localeOrganization from '@/views/authority/organization/locale/zh-CN'; +import localeResource from '@/views/authority/resource/locale/zh-CN'; import localeMonitor from '@/views/dashboard/monitor/locale/zh-CN'; @@ -60,6 +61,7 @@ ...localeUser, ...localeOrganization, + ...localeResource, ...localeMonitor, ...localeSearchTable, diff --git a/src/router/routes/modules/authority.ts b/src/router/routes/modules/authority.ts index de853c3..64a81e7 100644 --- a/src/router/routes/modules/authority.ts +++ b/src/router/routes/modules/authority.ts @@ -32,6 +32,16 @@ roles: ['*'], }, }, + { + path: 'resource', + name: 'resource', + component: () => import('@/views/authority/resource/index.vue'), + meta: { + locale: 'menu.resource.title', + requiresAuth: true, + roles: ['*'], + }, + }, ], }; diff --git a/src/views/authority/organization/index.vue b/src/views/authority/organization/index.vue index 8da1c6c..5088a73 100644 --- a/src/views/authority/organization/index.vue +++ b/src/views/authority/organization/index.vue @@ -194,6 +194,12 @@ } }; +const handleCancel = (type) => { + if (type == 1) { + visible.value = false; + } +}; + const OrganizationData = async (key) => { await OrganizationList(key).then((res) => { treeData.value = [...res.rows]; diff --git a/src/views/authority/resource/index.vue b/src/views/authority/resource/index.vue new file mode 100644 index 0000000..38f1e06 --- /dev/null +++ b/src/views/authority/resource/index.vue @@ -0,0 +1,248 @@ +<template> + <div class="container"> + <authheader :items="menuTips"></authheader> + <a-row :gutter="20"> + <a-col :span="8"> + <a-card :title="$t('menu.resource.title')" :bordered="false" + :style="{ width: '100%',height: '900px', 'overflow-y': 'auto' }"> + <a-tree + class="tree-demo" + draggable + blockNode + :data="treeData" + :show-line="showLine" + :fieldNames="{ + key:'menuId', + title:'menuName', + children:'children', + }" + @drop="onDrop" + @select="showDetail" + > + <template #extra="nodeData"> + <IconPlus + style="position: absolute; right: 60px; font-size: 12px; top: 10px; color: #3370ff;" + @click="() => onIconClick(nodeData)" + /> + <IconDelete style="position: absolute; right: 40px; font-size: 12px; top: 10px; color: #3370ff;" + @click="() => onIconClickDelete(nodeData)" /> + </template> + </a-tree> + + </a-card> + </a-col> + <a-col :span="16"> + <a-card :title="$t('menu.resource.detail')" :bordered="false" :style="{ width: '100%' }"> + <a-form :model="resourceform" layout="horizontal"> + <a-form-item field="parentName" label="涓婄骇璧勬簮" disabled> + <a-input v-model="resourceform.parentName" /> + </a-form-item> + <a-form-item field="status" label="璧勬簮鐘舵��"> + <a-switch checked-value="0" unchecked-value="1" v-model="resourceform.status"></a-switch> + </a-form-item> + <a-form-item field="menuName" label="璧勬簮鍚嶇О"> + <a-input v-model="resourceform.menuName" /> + </a-form-item> + <a-form-item field="menuType" label="璧勬簮绫诲瀷"> + <a-select v-model="resourceform.menuType" :options="options" :field-names="fieldNames" + :style="{width:'320px'}" + placeholder="璇烽�夋嫨" /> + + </a-form-item> + <a-form-item field="perms" label="璧勬簮鎺у埗鏉冮檺瀛楃"> + <a-input v-model="resourceform.perms" /> + </a-form-item> + <a-form-item field="component" label="璧勬簮鍦板潃" style="align: start"> + <a-input v-model="resourceform.component" /> + </a-form-item> + <a-form-item> + <a-space> + <a-button @click="editresource">淇濆瓨</a-button> + <a-button @click="reset(resourceform.menuId)">閲嶇疆</a-button> + </a-space> + </a-form-item> + </a-form> + </a-card> + </a-col> + </a-row> + <a-modal width="50%" v-model:visible="visible" title="鏂板" @cancel="handleCancel" @ok="addresource"> + <a-form :model="resourceform" layout="horizontal"> + <a-form-item field="parentName" label="涓婄骇璧勬簮" disabled> + <a-input v-model="resourceform.parentName" /> + </a-form-item> + <a-form-item field="status" label="璧勬簮鐘舵��"> + <a-switch checked-value="0" unchecked-value="1" v-model="resourceform.status"></a-switch> + </a-form-item> + <a-form-item field="menuName" label="璧勬簮鍚嶇О"> + <a-input v-model="resourceform.menuName" /> + </a-form-item> + <a-form-item field="menuType" label="璧勬簮绫诲瀷"> + <a-select v-model="resourceform.menuType" :options="options" :field-names="fieldNames" + :style="{width:'320px'}" + placeholder="璇烽�夋嫨" /> + </a-form-item> + <a-form-item field="perms" label="璧勬簮鎺у埗鏉冮檺瀛楃"> + <a-input v-model="resourceform.perms" /> + </a-form-item> + <a-form-item field="component" label="璧勬簮鍦板潃" style="align: start"> + <a-input v-model="resourceform.component" /> + </a-form-item> + </a-form> + </a-modal> + </div> +</template> + +<script lang="ts" setup> +import { ref } from "vue"; +import { IconPlus } from "@arco-design/web-vue/es/icon"; +import { Resource, ResourceAdd, ResourceById, ResourceDelete, ResourceList, ResourceUpdate } from "@/api/authority"; +import Authheader from "@/views/authority/components/authheader.vue"; +import { Modal } from "@arco-design/web-vue"; + +let visible = ref(false); +let treeData = ref([]); +let showLine = ref(true); +let menuTips = ref(["鏉冮檺绠$悊", "璧勬簮"]); +const fieldNames = { value: "key", label: "value" }; +// 0鐩綍 1鑿滃崟 2鎸夐挳 +let options = ref([ + { + key: "0", + value: "鐩綍" + }, + { + key: "1", + value: "鑿滃崟" + }, + { + key: "2", + value: "鎸夐挳" + } +]); +let resourceform = ref<Resource>({ + component: "", + createTime: "", + description: "", + icon: "", + menuId: "", + menuName: "", + menuType: "", + orderNum: "", + parentId: "", + parentName: "", + children: [], + path: "", + perms: "", + status: "", + syesourcetype: "", + target: "", + updateTime: "" +}); + +const onIconClick = (nodeData) => { + resourceform.value.parentId = nodeData.menuId; + visible.value = true; +}; + +const addresource = async () => { + await ResourceAdd({ + ...resourceform.value + } as unknown as Resource).then((res) => { + ResourceData(""); + }); +}; + +const onIconClickDelete = (nodeData) => { + ResourceDelete(nodeData.menuId).then(() => { + ResourceData(""); + }); +}; + +const showDetail = (id) => { + ResourceById(id).then((res) => { + resourceform.value = { ...res.data }; + }); +}; +const editresource = () => { + ResourceUpdate({ + ...resourceform.value + } as unknown as Resource).then((res) => { + ResourceData(""); + Modal.success({ + title: "淇濆瓨鎴愬姛", + content: "淇濆瓨鎴愬姛" + }); + }); +}; +const reset = (id) => { + ResourceById(id).then((res) => { + resourceform.value = { ...res.data }; + }); +}; + +const onDrop = ({ dragNode, dropNode, dropPosition }) => { + const data = treeData.value; + ResourceUpdate({ + orderNum: "0", parentId: dropNode.menuId, menuId: dragNode.menuId + }); + const loop = (data, key, callback) => { + data.some((item, index, arr) => { + if (item.menuId === key) { + callback(item, index, arr); + return true; + } + if (item.children) { + return loop(item.children, key, callback); + } + return false; + }); + }; + + loop(data, dragNode.menuId, (_, index, arr) => { + arr.splice(index, 1); + }); + + if (dropPosition === 0) { + loop(data, dropNode.menuId, (item) => { + item.children = item.children || []; + item.children.push(dragNode); + }); + } else { + loop(data, dropNode.menuId, (_, index, arr) => { + arr.splice(dropPosition < 0 ? index : index + 1, 0, dragNode); + }); + } +}; + +const handleCancel = (type) => { + if (type == 1) { + visible.value = false; + } +}; + +const ResourceData = async (key) => { + await ResourceList(key).then((res) => { + treeData.value = [...res.rows]; + }); +}; + +ResourceData(""); +</script> + + +<style scoped> +.tree-demo :deep(.tree-node-dropover) > :deep(.arco-tree-node-title), +.tree-demo :deep(.tree-node-dropover) > :deep(.arco-tree-node-title):hover { + animation: blinkBg 0.4s 2; +} + +@keyframes blinkBg { + 0% { + background-color: transparent; + } + + 100% { + background-color: var(--color-primary-light-1); + } +} +</style> diff --git a/src/views/authority/resource/locale/en-US.ts b/src/views/authority/resource/locale/en-US.ts new file mode 100644 index 0000000..114060f --- /dev/null +++ b/src/views/authority/resource/locale/en-US.ts @@ -0,0 +1,5 @@ +export default { + "menu.resource.title": "resource", + 'menu.resource.detail': 'Detail', +}; +// export default { "menu.user.title": "Account" }; \ No newline at end of file diff --git a/src/views/authority/resource/locale/zh-CN.ts b/src/views/authority/resource/locale/zh-CN.ts new file mode 100644 index 0000000..e70b222 --- /dev/null +++ b/src/views/authority/resource/locale/zh-CN.ts @@ -0,0 +1,4 @@ +export default { + 'menu.resource.title': '璧勬簮', + 'menu.resource.detail': '璇︽儏', +}; \ No newline at end of file -- Gitblit v1.8.0