Browse Source

权限系统

space2
han2015 3 months ago
parent
commit
2ed1aa529c
  1. 10
      src/api/doc/type.ts
  2. 51
      src/api/hr/people/share_ctrol.ts
  3. 36
      src/store/modules/orgMember.ts
  4. 4
      src/views/doc/agent.vue
  5. 168
      src/views/doc/manage.vue
  6. 2
      src/views/doc/sharePermission.vue
  7. 166
      src/views/doc/space.vue
  8. 348
      src/views/doc/spacePermission.vue

10
src/api/doc/type.ts

@ -15,6 +15,7 @@ export interface matterPage{
deleted?:boolean; deleted?:boolean;
orderDir?:string; orderDir?:string;
name?:string; name?:string;
space?:string;
orderCreateTime?:string; orderCreateTime?:string;
} }
@ -31,8 +32,14 @@ export interface matterInfo{
deleted?:boolean; deleted?:boolean;
expireInfinity?:boolean; expireInfinity?:boolean;
expireTime?:string; expireTime?:string;
permitVal?:number; //该值是当前用户permits的解析结果
permits?:matterPermit;
}
export interface matterPermit{
id:number;
MatterUuid:string;
data:string;
} }
export interface shareItem{ export interface shareItem{
name?:string; name?:string;
updateTime?:string; updateTime?:string;
@ -47,6 +54,7 @@ export interface shareItem{
} }
export interface matterTree extends matterInfo { export interface matterTree extends matterInfo {
manager?:boolean;
children:matterTree[] children:matterTree[]
} }

51
src/api/hr/people/share_ctrol.ts

@ -74,7 +74,12 @@ export function getPermitedList(uid:string,data:{uuid:string}): AxiosPromise<{pe
/** /**
* *
*/ */
export function getSpaceMemberList(uid:string,data:{space?:string}): AxiosPromise<{members:string[],dprts:string[]}> { export function getSpaceMemberList(uid:string,data:{space?:string,matter:string}): AxiosPromise<{
members:string[],
dprts:string[],
managers:string,
permits:Object,
}> {
return request({ return request({
url: '/hxpan/api/space/members', url: '/hxpan/api/space/members',
method: 'post', method: 'post',
@ -86,6 +91,50 @@ export function getSpaceMemberList(uid:string,data:{space?:string}): AxiosPromis
}); });
} }
/**
*
*/
export function addSpaceManager(uid:string,data:{space:string,mangers:string}): AxiosPromise<{members:string[],dprts:string[]}> {
return request({
url: '/hxpan/api/space/addmanagers',
method: 'post',
headers: {
'Identifier':uid,
'Content-Type': 'application/x-www-form-urlencoded'
},
data: data
});
}
/**
* matter权限
*/
export function updateSpaceMetterPermit(uid:string,data:{space:string,matter:string,permits:Object}): AxiosPromise<{members:string[],dprts:string[]}> {
return request({
url: '/hxpan/api/space/permit/update',
method: 'post',
headers: {
'Identifier':uid,
},
data: data
});
}
/**
* matter特定权限
*/
export function resetSpaceMatterPermit(uid:string,data:{space:string,matter:string}): AxiosPromise<{members:string[],dprts:string[]}> {
return request({
url: '/hxpan/api/space/permit/reset',
method: 'post',
headers: {
'Identifier':uid,
'Content-Type': 'application/x-www-form-urlencoded'
},
data: data
});
}
/** /**
* *
*/ */

36
src/store/modules/orgMember.ts

@ -0,0 +1,36 @@
import { defineStore } from 'pinia'
import { ref} from 'vue';
import request from "@/utils/request";
export const useOrgMemberStore = defineStore('orgMember', () => {
interface OrgMemberItem {
id: string;
label: string;
children?:OrgMemberItem[];
}
const listMap = ref<Record<string, string>>({})
const dataTree = ref<OrgMemberItem>({ id: '', label: '', children: [] })
async function init() {
await request({
url: "/javasys/lowCode/transfer/getOrgAndManTree",
method: "post",
}).then((response) => {
// assuming response.data is an array of OrgMemberItem
dataTree.value=response.data
handleChildren(response.data.children)
});
}
function handleChildren(childs:any[]){
childs.forEach(item => {
listMap.value[item.id] = item.label;
if(item.children){
handleChildren(item.children)
}
});
}
init()
return { listMap,dataTree }
})

4
src/views/doc/agent.vue

@ -230,7 +230,7 @@ onMounted(() => {
<VueMarkdown :markdown="respMsg" :rehype-plugins="[rehypeRaw]" class="t_resp"></VueMarkdown> <VueMarkdown :markdown="respMsg" :rehype-plugins="[rehypeRaw]" class="t_resp"></VueMarkdown>
</div> </div>
<div class="question_com" :class="{newquestion:conversation!='' || !inputState}"> <div class="question_com" :class="{newquestion:conversation!='' || !inputState}">
<h1 v-show="conversation =='' && inputState" style="font-size: 78px;margin: 10px;">恒信高科AI平台</h1> <h1 v-show="conversation =='' && inputState" style="font-size: 56px;margin: 10px;">恒信高科AI平台</h1>
<el-checkbox-group v-model="checkedModel" style="display:flex; margin-bottom: 10px;"> <el-checkbox-group v-model="checkedModel" style="display:flex; margin-bottom: 10px;">
<el-checkbox-button v-for="mod in aimodels" :value="mod.key"> <el-checkbox-button v-for="mod in aimodels" :value="mod.key">
{{ mod.name }} {{ mod.name }}
@ -288,7 +288,7 @@ onMounted(() => {
align-self: start; align-self: start;
line-height: 30px; line-height: 30px;
margin: 20px 33px; margin: 20px 33px;
font-size: 18px; font-size: 16px;
color: black; color: black;
} }
.dynamic-width-message-box-byme .el-message-box__message{ .dynamic-width-message-box-byme .el-message-box__message{

168
src/views/doc/manage.vue

@ -8,26 +8,22 @@ import { getExpirTime, getFileIcon, readableSize,fileType} from "./tools"
import sharePermission from './sharePermission.vue'; import sharePermission from './sharePermission.vue';
import { useUserStore } from "@/store/modules/user"; import { useUserStore } from "@/store/modules/user";
import { getMatterList,postCreateDir,postDelMatter,postCreateShare,postMatterRename,postDelMatBatch,getMySpaces,doCreateSpace} from "@/api/doc/index" import { getMatterList,postCreateDir,postDelMatter,postCreateShare,postMatterRename,postDelMatBatch,getMySpaces,doCreateSpace} from "@/api/doc/index"
import { matterPage,matterInfo,respCreateShare,matterTree, doFileUpload} from "@/api/doc/type" import { matterPage,matterInfo,respCreateShare,matterTree, doFileUpload,matterPermit} from "@/api/doc/type"
import { h } from 'vue' import { h } from 'vue'
import router from "@/router";
import { import {
Delete, Delete,View,Download,Share,Search,Edit,
View, Avatar,Plus,Grid,List,
Download, Setting,
Share,
Search,
Edit,
Promotion,
Folder,
Avatar,
Plus,
Grid,
List,
} from '@element-plus/icons-vue' } from '@element-plus/icons-vue'
import {ElSelect,ElOption, ElText,ElInput,TableInstance,ElMessage,UploadFile,UploadFiles,ElPagination,ElTree,TreeNode} from "element-plus"; import {ElSelect,ElOption, ElText,ElInput,TableInstance,ElMessage,UploadFile,
UploadFiles,ElPagination,ElTree,TreeNode,ElDropdown,ElDropdownItem} from "element-plus";
import preview from './preview.vue'; import preview from './preview.vue';
import space from './space.vue'; import space from './space.vue';
import spacePermission from './spacePermission.vue';
import SvgIcon from "@/components/SvgIcon/index.vue"; import SvgIcon from "@/components/SvgIcon/index.vue";
import {doDelSpace} from "@/api/doc/space"
import Space from "./space.vue";
//TODO: add file icons done! //TODO: add file icons done!
//TODO: click on table-item 1preview on file ..................... //TODO: click on table-item 1preview on file .....................
@ -44,12 +40,13 @@ import SvgIcon from "@/components/SvgIcon/index.vue";
const userStore = useUserStore(); const userStore = useUserStore();
const uid=btoa("p0"+userStore.userInfoCont.userId); const uid=btoa("p0"+userStore.userInfoCont.userId);
const rawUid="p0"+userStore.userInfoCont.userId
const siteHost=document.location.origin; const siteHost=document.location.origin;
const apiURL=import.meta.env.VITE_APP_BASE_API+"/hxpan/api" const apiURL=import.meta.env.VITE_APP_BASE_API+"/hxpan/api"
const matterList = ref<matterInfo[]>([]) const matterList = ref<matterInfo[]>([])
const searchname=ref("") const searchname=ref("")
const newdir=ref("") // const newdirName=ref("") //
const currentHoverRow=ref("") //table const currentHoverRow=ref("") //table
const selectedValue = ref("sixhour") // const selectedValue = ref("sixhour") //
const tabSelected=ref<matterInfo[]>([]) //table const tabSelected=ref<matterInfo[]>([]) //table
@ -65,8 +62,7 @@ const multipleTableRef = ref<TableInstance>()
const paginInfo = ref({ page: 0, total: 0 }) const paginInfo = ref({ page: 0, total: 0 })
const PRIVATESPACE = ref(true) // 2 const PRIVATESPACE = ref(true) // 2
const SpaceID= ref<{name:string,uuid:string,userUuid:string}>({}) //spaceid const SpaceID= ref<{name:string,uuid:string,userUuid:string,manager:boolean,permits:matterPermit}>({}) //spaceid
const SpaceList=ref<{name:string,uuid:string,userUuid:string}[]>([])
const spaceEleRef = ref() //space,spaceTreeRefspaceTree const spaceEleRef = ref() //space,spaceTreeRefspaceTree
const spaceTreeData=ref<matterTree[]>([])//{name:'',uuid:'root',children:[]} const spaceTreeData=ref<matterTree[]>([])//{name:'',uuid:'root',children:[]}
const spaceTreeRef = ref(); //space const spaceTreeRef = ref(); //space
@ -75,7 +71,7 @@ let spaceNodeUid="" //用来判断树组件的展开和关闭,如何只是展
const modListOrGrild=ref(true) const modListOrGrild=ref(true)
const Departs = computed(() => { const Departs = computed(() => {
return `${userStore.userInfoCont.company},${userStore.userInfoCont.department},${userStore.userInfoCont.organization}` return `${'p0'+userStore.userInfoCont.userId},${userStore.userInfoCont.company},${userStore.userInfoCont.department},${userStore.userInfoCont.organization}`
}) })
const uploadFormData = computed(() => { const uploadFormData = computed(() => {
@ -217,7 +213,9 @@ function onDelMatBatch(){
}).then(()=>{ }).then(()=>{
postDelMatBatch(uid,{ postDelMatBatch(uid,{
"uuids":tabSelected.value.map((item:matterInfo)=>item.uuid).join(",") "uuids":tabSelected.value.map((item:matterInfo)=>item.uuid).join(",")
}).then(()=>onLoadMatterList()) }).then(()=>{
router.replace({ query: { t: Date.now() } })
})
}) })
} }
@ -323,15 +321,16 @@ function onCreateDir(){
postCreateDir(uid,{ postCreateDir(uid,{
userUuid:uid, userUuid:uid,
puuid:currentNode.value.uuid, puuid:currentNode.value.uuid,
name:newdir.value, name:newdirName.value,
}).then((resp)=> { }).then((resp)=> {
newdir.value="" newdirName.value=""
//treeappend //treeappend
treeRef.value.append( treeRef.value.append(
{uuid:resp.data.uuid,dir:false,name:resp.data.name,puuid:resp.data.puuid}, {uuid:resp.data.uuid,dir:false,name:resp.data.name,puuid:resp.data.puuid},
currentNode.value.uuid currentNode.value.uuid
) )
//onLoadMatterList() matterList.value?.shift() //
matterList.value?.push(resp.data) //
}) })
.catch((e)=>{ .catch((e)=>{
ElMessage.error(e.msg) ElMessage.error(e.msg)
@ -607,7 +606,8 @@ function onNewSpace(){
}).then(() => { }).then(() => {
if(newname.value!==""){ if(newname.value!==""){
doCreateSpace(uid,newname.value).then((resp)=>{ doCreateSpace(uid,newname.value).then((resp)=>{
SpaceList.value.push({name:resp.data.name,uuid:resp.data.uuid,userUuid:"p0"+userStore.userInfoCont.userId}) //spaceTreeRef.value.append({name:resp.data.name,uuid:resp.data.uuid,dir:false,userUuid:resp.data.userUuid})
router.replace({ query: { t: Date.now() } }) //
}) })
} }
}) })
@ -625,7 +625,9 @@ function onSpaceNodeClick(data:matterTree,node:TreeNode,self:any,env:any){
SpaceID.value={ SpaceID.value={
name: data.name ?? "", name: data.name ?? "",
uuid: data.uuid ?? "", uuid: data.uuid ?? "",
userUuid: data.userUuid ?? "" userUuid: data.userUuid ?? "",
manager: data.manager ?? false,
permits:data.permits ??{}
}; };
PRIVATESPACE.value=false; PRIVATESPACE.value=false;
}else{ }else{
@ -634,7 +636,8 @@ function onSpaceNodeClick(data:matterTree,node:TreeNode,self:any,env:any){
puuid: data.puuid, puuid: data.puuid,
name:data.name, name:data.name,
agent:data.agent, agent:data.agent,
dir:true dir:true,
permits:data.permits
} }
// //
spaceEleRef.value.handleDoubleClick(matter) spaceEleRef.value.handleDoubleClick(matter)
@ -646,6 +649,41 @@ function flushSpaceTree(uuid:string,data:matterTree[]){
spaceTreeRef.value.updateKeyChildren(uuid,data) spaceTreeRef.value.updateKeyChildren(uuid,data)
} }
//
function onDeleteSpace(row:matterInfo){
ElMessageBox.confirm(`确认删除空间 ( ${row.name}) ? 空间内所有文件将不可恢复!取消则放弃删除操作。`, "警告", {
confirmButtonText: "确定删除",
cancelButtonText: "取消",
type: "warning",
}).then(()=>{
doDelSpace(uid,{
"space":row.uuid,
}).then(()=>{
router.replace({ query: { t: Date.now() } })
})
})
}
//matter
function onDelSpaceMatter(row:matterInfo){
if(row.puuid){
spaceEleRef.value.onDelMatter(row)
}else{
onDeleteSpace(row)
}
}
//
function onSpacePManage(row:matterInfo){
dynamicVNode.value=h(spacePermission,{
uid:rawUid, //uuid
uuid:row.uuid, //uuid
suid:SpaceID.value.userUuid,
spaceid:SpaceID.value.uuid, //uuid
closeFunc:()=>dynamicVNode.value=null
})
}
//------------------------------------------------------ //------------------------------------------------------
//http://172.20.2.87:6010/api/alien/preview/5a10aaf6-396e-4d9a-7e87-3c5c8029d4db/123.png?ir=fill_100_100 //http://172.20.2.87:6010/api/alien/preview/5a10aaf6-396e-4d9a-7e87-3c5c8029d4db/123.png?ir=fill_100_100
// //
@ -654,12 +692,12 @@ onMounted(() => {
{name:'个人空间',uuid:'root',dir:false}, {name:'个人空间',uuid:'root',dir:false},
currentNode.value.uuid currentNode.value.uuid
) )
// //
getMySpaces(uid,{roles:Departs}).then((resp)=>{ getMySpaces(uid,{roles:Departs.value}).then((resp)=>{
//SpaceList.value=resp.data
resp.data.forEach((item)=>{ resp.data.forEach((item)=>{
spaceTreeRef.value.append({name:item.name,uuid:item.uuid,dir:false,userUuid:item.userUuid}) let ismanager=false
if(item.userUuid==rawUid || item.managers.includes(rawUid)) ismanager=true;
spaceTreeRef.value.append({name:item.name,uuid:item.uuid,dir:false,userUuid:item.userUuid,manager:ismanager,permits:item.permits})
}) })
}) })
let val =localStorage.getItem("listOrGrid") let val =localStorage.getItem("listOrGrid")
@ -690,22 +728,41 @@ const handleSelectionChange = (val:matterInfo[]) => {
:load="onNodeExpand" :load="onNodeExpand"
:default-expanded-keys="['root']" :default-expanded-keys="['root']"
@node-click="onNodeClick" @node-click="onNodeClick"
/> >
<el-button style="margin: 10px 0px 10px auto;" :icon="Plus" @click="onNewSpace"> 共享空间</el-button> <template #default="{ node, data }">
<div class="tree-item">
<span>{{ node.label }}</span>
<el-button size="small" :icon="Delete" circle @click="(e)=>{ e.stopPropagation(); onDelMatter(data)}"></el-button>
</div>
</template>
</el-tree>
<div style="display:flex;margin-top: 9px;background-color: white;"><span style="align-content: center;margin-left: 21px;color: #686854;">共享空间</span> <el-button style="margin: 10px 0px 10px auto;" :icon="Plus" @click="onNewSpace"> </el-button></div>
<el-tree <el-tree
ref="spaceTreeRef" ref="spaceTreeRef"
style="max-width: 600px" style="max-width: 600px"
:data="spaceTreeData"
node-key="uuid" node-key="uuid"
accordion accordion
highlight-current highlight-current
lazy lazy
:props="{label: 'name',children:'children',isLeaf:'dir'}" :props="{label: 'name',children:'children',isLeaf:'dir'}"
@node-click="onSpaceNodeClick" @node-click="onSpaceNodeClick"
/> >
<ul style="background-color: white;max-width: 600px;"> <template #default="{ node, data }">
<li class="spaceitem" v-for="sp in SpaceList" @click="()=>{SpaceID=sp; PRIVATESPACE=false;}">{{ sp.name }}</li> <div class="tree-item">
</ul> <span>{{ node.label}}</span>
<el-dropdown v-if="SpaceID.manager">
<el-button size="small" :icon="Setting" circle ></el-button>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item @click="(e)=>{ e.stopPropagation(); onDelSpaceMatter(data)}">删除</el-dropdown-item>
<el-dropdown-item @click="(e)=>{ e.stopPropagation(); onSpacePManage(data)}">权限管理</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</div>
</template>
</el-tree>
</div> </div>
<div v-if="PRIVATESPACE" class="app_container"> <div v-if="PRIVATESPACE" class="app_container">
@ -742,9 +799,6 @@ const handleSelectionChange = (val:matterInfo[]) => {
<el-button @click="onShareMatter()">分享</el-button> <el-button @click="onShareMatter()">分享</el-button>
<el-button @click="onDelMatBatch">删除</el-button> <el-button @click="onDelMatBatch">删除</el-button>
</span> </span>
<el-button type="danger" plain @click="onShareMatter({uuid:currentNode.uuid,name:currentNode.name})">分享目录</el-button>
<el-button type="danger" plain @click="onDelMatter({uuid:currentNode.uuid,name:currentNode.name,dir:true,
puuid:currentNode.puuid,path:currentNode.path})">删除目录</el-button>
</el-col> </el-col>
<el-button-group style="margin:0 50px 0 auto;"> <el-button-group style="margin:0 50px 0 auto;">
<el-button :icon="List" @click="updateListOrGrid(true)"></el-button> <el-button :icon="List" @click="updateListOrGrid(true)"></el-button>
@ -766,8 +820,8 @@ const handleSelectionChange = (val:matterInfo[]) => {
<el-table-column type="selection" width="50" /> <el-table-column type="selection" width="50" />
<el-table-column width="450" property="name" label="文件名"> <el-table-column width="450" property="name" label="文件名">
<template #default="scope"> <template #default="scope">
<input type="text" autofocus placeholder="文件夹名" style="border:groove;height:30px;" v-model="newdir" @change="onCreateDir" v-if="scope.row.name===''" /> <input v-if="scope.row.name===''" v-model="newdirName" type="text" autofocus placeholder="文件夹名" style="border:groove;height:30px;" @change="onCreateDir" />
<div v-if="scope.row.name" style="display: flex; align-items: center;"> <div v-else style="display: flex; align-items: center;">
<svg-icon v-if="scope.row.dir" icon-class="folder-icon" size="30px"/> <svg-icon v-if="scope.row.dir" icon-class="folder-icon" size="30px"/>
<el-image v-else-if="getFileIcon(scope.row.name)==='img'" style="width: 30px;" :preview-src-list="[getImageDownloadURL(scope.row.uuid,scope.row.name)]" :src="getImagePreivewURL(scope.row.uuid,scope.row.name)" /> <el-image v-else-if="getFileIcon(scope.row.name)==='img'" style="width: 30px;" :preview-src-list="[getImageDownloadURL(scope.row.uuid,scope.row.name)]" :src="getImagePreivewURL(scope.row.uuid,scope.row.name)" />
<svg-icon v-else :icon-class="getFileIcon(scope.row.name)+'-icon'" size="30px" /> <svg-icon v-else :icon-class="getFileIcon(scope.row.name)+'-icon'" size="30px" />
@ -799,14 +853,19 @@ const handleSelectionChange = (val:matterInfo[]) => {
<div class="table-grid" v-else> <div class="table-grid" v-else>
<div class="grid-item" v-for="row in matterList"> <div class="grid-item" v-for="row in matterList">
<div class="grid"> <div class="grid">
<div class="grid-box" @click="handleMouseEnter(row)"> <div v-if="row.name===''">
<svg-icon icon-class="folder-icon" size="80px"/>
<input v-model="newdirName" type="text" autofocus placeholder="文件夹名" style="border:groove;height:30px;" @change="onCreateDir" />
</div>
<div v-else class="grid-box" @click="handleMouseEnter(row)">
<svg-icon v-if="row.dir" icon-class="folder-icon" size="80px"/> <svg-icon v-if="row.dir" icon-class="folder-icon" size="80px"/>
<el-image v-else-if="getFileIcon(row.name)==='img'" style="width: 80px;" :preview-src-list="[getImageDownloadURL(row.uuid,row.name)]" :src="getImagePreivewURL(row.uuid,row.name)" /> <el-image v-else-if="getFileIcon(row.name)==='img'" style="width: 80px;" :preview-src-list="[getImageDownloadURL(row.uuid,row.name)]" :src="getImagePreivewURL(row.uuid,row.name)" />
<svg-icon v-else :icon-class="getFileIcon(row.name)+'-icon'" size="80px"/> <svg-icon v-else :icon-class="getFileIcon(row.name)+'-icon'" size="80px"/>
<span style="margin: 5px 0;text-wrap-mode:nowrap;">{{ row.name }}</span> <span style="margin: 5px 0;text-wrap-mode:nowrap;">{{ row.name }}</span>
</div> </div>
</div> </div>
<div class="grid-menus" v-show="currentHoverRow === row.name"> <div v-if="row.name!=''" class="grid-menus" v-show="currentHoverRow === row.name">
<el-button v-if="getFileIcon(row.name)!='img'" size="small" :icon="View" circle @click="onPrivateView(row)"></el-button> <el-button v-if="getFileIcon(row.name)!='img'" size="small" :icon="View" circle @click="onPrivateView(row)"></el-button>
<el-button size="small" :icon="Share" circle @click="onShareMatter(row)"></el-button> <el-button size="small" :icon="Share" circle @click="onShareMatter(row)"></el-button>
<el-button size="small" :icon="Download" circle @click="onDownload(row)"></el-button> <el-button size="small" :icon="Download" circle @click="onDownload(row)"></el-button>
@ -822,13 +881,13 @@ const handleSelectionChange = (val:matterInfo[]) => {
</el-row> </el-row>
</div> </div>
<div v-else class="app_container"> <div v-else class="app_container">
<space ref="spaceEleRef" :uid="uid" :tree="spaceTreeRef" :listOrGrid="modListOrGrild" <space ref="spaceEleRef" :uid="uid" :raw-uid="rawUid" :listOrGrid="modListOrGrild"
:spaceid="SpaceID.uuid" :roles="Departs" :spacename="SpaceID.name" :owner="SpaceID.userUuid" :spaceid="SpaceID.uuid" :roles="Departs" :spacename="SpaceID.name" :space-permit="SpaceID.permits"
:owner="SpaceID.userUuid" :ismanager="SpaceID.manager"
:officeHost="officeHost" :site-host="siteHost" :api-u-r-l="apiURL" :officeHost="officeHost" :site-host="siteHost" :api-u-r-l="apiURL"
:flushSpaceTree="flushSpaceTree"></space> :flushSpaceTree="flushSpaceTree"></space>
</div> </div>
<div v-if="dynamicVNode"> <div v-if="dynamicVNode">
<component :is="dynamicVNode" /> <component :is="dynamicVNode" />
</div> </div>
@ -848,8 +907,25 @@ const handleSelectionChange = (val:matterInfo[]) => {
--el-tree-node-content-height:43px; --el-tree-node-content-height:43px;
--el-tree-expand-icon-color:#4c4c4e; --el-tree-expand-icon-color:#4c4c4e;
} }
}
.tree-item{
display: flex;
width: 100%;
button{
display: none;
margin: 0 5px 0 auto;
}
}
.tree-item:hover button{
display: block;
}
.el-dropdown{
margin: 0 5px 0 auto;
} }
.app_container { .app_container {
padding: 10px 30px 0px 30px; padding: 10px 30px 0px 30px;
height: calc(100% - 10px); height: calc(100% - 10px);

2
src/views/doc/sharePermission.vue

@ -151,7 +151,7 @@ onMounted(()=>{
<template> <template>
<el-dialog :model-value="true" :style="{'max-height': '650px'}" v-on:close="closeFunc()"> <el-dialog :model-value="true" :style="{'max-height': '650px'}" v-on:close="closeFunc()">
<template #header> <template #header>
<span>权限管理</span> <span>成员管理</span>
</template> </template>
<div style="display: grid;width: 100%;grid-template-columns:1fr 1fr;"> <div style="display: grid;width: 100%;grid-template-columns:1fr 1fr;">
<div class="menus_tree"> <div class="menus_tree">

166
src/views/doc/space.vue

@ -6,8 +6,9 @@
<script lang="ts" setup> <script lang="ts" setup>
import { getFileIcon, readableSize,fileType} from "./tools" import { getFileIcon, readableSize,fileType} from "./tools"
import sharePermission from './sharePermission.vue'; import sharePermission from './sharePermission.vue';
import { matterPage,matterInfo,matterTree,doFileUpload} from "@/api/doc/type" import spacePermission from './spacePermission.vue';
import { doAccessManage,getSpaceMatterList,doCreateSpaceDir,doDelSpaceMatter,doDelSpace, import { matterPage,matterInfo,matterTree,doFileUpload,matterPermit} from "@/api/doc/type"
import { doAccessManage,getSpaceMatterList,doCreateSpaceDir,doDelSpaceMatter,
doAiTraining ,doCreateAiagent} from "@/api/doc/space" doAiTraining ,doCreateAiagent} from "@/api/doc/space"
import { h } from 'vue' import { h } from 'vue'
import { import {
@ -17,15 +18,18 @@ import {
Plus, Plus,
Edit, Edit,
Folder, Folder,
Setting,
} from '@element-plus/icons-vue' } from '@element-plus/icons-vue'
import {ElMessage,UploadFile,UploadFiles,ElPagination} from "element-plus"; import {ElMessage,UploadFile,UploadFiles,ElPagination} from "element-plus";
import aiagent from './agent.vue'; import aiagent from './agent.vue';
import router from "@/router"; import router from "@/router";
import SvgIcon from "@/components/SvgIcon/index.vue"; import SvgIcon from "@/components/SvgIcon/index.vue";
import { useOrgMemberStore } from "@/store/modules/orgMember";
const orgMembers = useOrgMemberStore() //
const defaultAiAgent=import.meta.env.VITE_DEFAULT_AI_AGENT const defaultAiAgent=import.meta.env.VITE_DEFAULT_AI_AGENT
const matterList = ref<matterInfo[]>([]) const matterList = ref<matterInfo[]>([])
const newdir=ref("") // const newdirName=ref("") //
const currentHoverRow=ref("") //table const currentHoverRow=ref("") //table
const breadcrumbList=ref<matterInfo[]>([{name:"根目录",uuid:"root", dir:true}]) // const breadcrumbList=ref<matterInfo[]>([{name:"根目录",uuid:"root", dir:true}]) //
@ -36,6 +40,17 @@ let isNewNode=true //用来减少父组件树的重置
const dynamicVNode = ref<VNode | null>(null) //permission const dynamicVNode = ref<VNode | null>(null) //permission
const paginInfo = ref({ page: 0, total: 0 }) const paginInfo = ref({ page: 0, total: 0 })
const CutLevelPermit=ref(0)
enum PERMITS {
FORBID, //0
VIEW, //1
DOWNLOAD, //2
UPLOAD, //3
UPANDDOWNLOAD, //4
EDIT, //5
MANAGER, //6
}
//-----------AI--------------------- //-----------AI---------------------
//const agent=ref<{model:boolean,name:string}>({}) //const agent=ref<{model:boolean,name:string}>({})
const currentAgent=ref<{model:boolean,name:string,uuid:string}>({}) const currentAgent=ref<{model:boolean,name:string,uuid:string}>({})
@ -44,7 +59,8 @@ const currentAgent=ref<{model:boolean,name:string,uuid:string}>({})
const props = withDefaults(defineProps<{ const props = withDefaults(defineProps<{
uid:string, //uuid,base64,Identifierbase64 uid:string, //uuid,base64,Identifierbase64
tree:object, rawUid:string,
//tree:object,
spaceid:string, spaceid:string,
spacename:string, spacename:string,
officeHost:string, officeHost:string,
@ -53,6 +69,8 @@ const props = withDefaults(defineProps<{
apiURL:string, apiURL:string,
roles:string, roles:string,
listOrGrid:boolean, listOrGrid:boolean,
ismanager:boolean,
spacePermit:matterPermit,
flushSpaceTree:(uuid:string,data:matterTree[])=>void flushSpaceTree:(uuid:string,data:matterTree[])=>void
}>(),{}) }>(),{})
@ -96,21 +114,18 @@ function onAccessManage(){
}) })
} }
// //
function onDeleteSpace(){ function onSpacePManage(row:matterInfo){
ElMessageBox.confirm(`确认删除空间 ( ${props.spacename}) ? 空间内所有文件将不可恢复!取消则放弃删除操作。`, "警告", { dynamicVNode.value=h(spacePermission,{
confirmButtonText: "确定删除", uid:props.rawUid, //uuid
cancelButtonText: "取消", uuid:row.uuid, //uuid
type: "warning", suid:props.owner,
}).then(()=>{ spaceid:props.spaceid, //uuid
doDelSpace(props.uid,{ closeFunc:()=>dynamicVNode.value=null
"space":props.spaceid,
}).then(()=>{
router.replace({ query: { t: Date.now() } })
})
}) })
} }
//---------------------------------------- //----------------------------------------
// //
function onDelMatter(row:matterInfo){ function onDelMatter(row:matterInfo){
@ -163,13 +178,42 @@ function onLoadMatterList(){
getSpaceMatterList(props.uid,_page).then((resp)=>{ getSpaceMatterList(props.uid,_page).then((resp)=>{
//page+1 index1apiindex0 //page+1 index1apiindex0
paginInfo.value={total:resp.data.totalPages, page:resp.data.page} paginInfo.value={total:resp.data.totalPages, page:resp.data.page}
if (props.ismanager) {
resp.data.data.forEach(item => {
item.permitVal=PERMITS.MANAGER
})
matterList.value=resp.data.data matterList.value=resp.data.data
}else{
matterList.value=resp.data.data.filter(item=>{ //
if(item.permits.ID==0){
item.permitVal=CutLevelPermit.value
}else{
//
let _pert: Record<string, number>
_pert = JSON.parse(item.permits!.data)
let val=_pert[props.rawUid.replace("p0","")]
if(val){
item.permitVal = val
}else{
item.permitVal = PERMITS.FORBID //
}
}
if(item.permitVal>0){
return true
}
return false
})
}
//使 //使
let node_data = resp.data.data.filter((item) => { let node_data = matterList.value.filter(item=> {
return item.dir return item.dir
}).map(val => { }).map(val => {
const copy = structuredClone(val) const copy = structuredClone(toRaw(val))
copy.dir = !copy.dir copy.dir = !copy.dir
return copy return copy
}) })
@ -199,11 +243,11 @@ function createDir(){
function onCreateDir(){ function onCreateDir(){
doCreateSpaceDir(props.uid,{ doCreateSpaceDir(props.uid,{
puuid:currentNode.value.uuid, puuid:currentNode.value.uuid,
name:newdir.value, name:newdirName.value,
space:props.spaceid, space:props.spaceid,
roles:props.roles, roles:props.roles,
}).then((resp)=> { }).then((resp)=> {
newdir.value="" newdirName.value=""
onLoadMatterList() onLoadMatterList()
}) })
.catch((e)=>{ .catch((e)=>{
@ -215,12 +259,30 @@ function onCreateDir(){
// //
function handleDoubleClick(row:matterInfo,ind?:number){ function handleDoubleClick(row:matterInfo,ind?:number){
if(row.dir){ if(row.dir){
//
if(row.permitVal){
CutLevelPermit.value=row.permitVal
}else{
if (props.ismanager) {
CutLevelPermit.value=9
}else{
let _pert: Record<string, number>
_pert = JSON.parse(row.permits!.data)
let val=_pert[props.rawUid.replace("p0","")]
if(val){
CutLevelPermit.value = val
}else{
CutLevelPermit.value = PERMITS.FORBID //
}
}
}
if(row.agent){ if(row.agent){
currentAgent.value={name:row.name,model:false,uuid:row.uuid} currentAgent.value={name:row.name,model:false,uuid:row.uuid}
} }
isNewNode=true isNewNode=true
//1 //1
//2: //2:
if(currentNode.value.puuid==row.uuid || row.uuid=="root") isNewNode=false if(currentNode.value.puuid==row.uuid || row.uuid=="root") isNewNode=false
currentNode.value=row currentNode.value=row
onLoadMatterList() onLoadMatterList()
@ -249,6 +311,10 @@ function handleDoubleClick(row:matterInfo,ind?:number){
} }
} }
function checkMatterPermit(){
}
function handleMouseEnter(row:any){ function handleMouseEnter(row:any){
currentHoverRow.value=row.name currentHoverRow.value=row.name
} }
@ -429,6 +495,8 @@ async function onlyOfficeEdit(row:matterInfo){
const info =btoa(encodeURIComponent(`${row.userUuid}/root${row.path}`)) // const info =btoa(encodeURIComponent(`${row.userUuid}/root${row.path}`)) //
const _url=`${props.siteHost}${props.apiURL}/space/download/${row.uuid}/${row.name}?space=${props.spaceid}` const _url=`${props.siteHost}${props.apiURL}/space/download/${row.uuid}/${row.name}?space=${props.spaceid}`
window.open(`/#/onlyoffice?name=${row.name}&dtype=${_type}&info=${info}&verify=${_verify}&fileurl=`+window.btoa(encodeURIComponent(_url)),"_blank") window.open(`/#/onlyoffice?name=${row.name}&dtype=${_type}&info=${info}&verify=${_verify}&fileurl=`+window.btoa(encodeURIComponent(_url)),"_blank")
}).catch(()=>{
console.log("close")
}) })
} }
@ -448,6 +516,19 @@ onMounted(() => {
//AI //AI
currentAgent.value={name:"通用AI",model:false,uuid:defaultAiAgent} currentAgent.value={name:"通用AI",model:false,uuid:defaultAiAgent}
if (props.ismanager) {
CutLevelPermit.value=PERMITS.MANAGER
}else{
let _pert: Record<string, number>
_pert = JSON.parse(props.spacePermit.data)
let val=_pert[props.rawUid.replace("p0","")]
if(val){
CutLevelPermit.value = val
}else{
CutLevelPermit.value = PERMITS.FORBID //
}
}
onLoadMatterList() onLoadMatterList()
}); });
@ -455,7 +536,7 @@ const handleSelectionChange = (val:matterInfo[]) => {
tabSelected.value = val tabSelected.value = val
} }
defineExpose({handleDoubleClick}) defineExpose({handleDoubleClick,onDelMatter})
// //
function isOwner(){ function isOwner(){
@ -477,7 +558,7 @@ function isOwner(){
</el-row> </el-row>
<el-row :gutter="24"> <el-row :gutter="24">
<el-col :span="14"> <el-col :span="14" v-if="CutLevelPermit>=PERMITS.UPLOAD">
<div class="el-button el-button--default" style="position: relative;"> <div class="el-button el-button--default" style="position: relative;">
<input type="file" style="position: absolute;opacity: 0;width: 50px;" <input type="file" style="position: absolute;opacity: 0;width: 50px;"
@change="onCustomUpload" multiple /> @change="onCustomUpload" multiple />
@ -493,14 +574,12 @@ function isOwner(){
文件夹上传 文件夹上传
</div> </div>
<el-button @click="createDir">新建目录</el-button> <el-button @click="createDir">新建目录</el-button>
<el-button type="danger" plain @click="onDelMatter({uuid:currentNode.uuid,name:currentNode.name,dir:true,
puuid:currentNode.puuid,path:currentNode.path})">删除目录</el-button>
</el-col> </el-col>
<el-button style="margin-left: auto;" @click="()=>currentAgent.model=true">AI助手</el-button> <el-button style="margin-left: auto;" @click="()=>currentAgent.model=true">AI助手</el-button>
<el-button-group v-if="isOwner()" class="control" style="margin: 0 10px;"> <el-button-group v-if="isOwner()" class="control" style="margin: 0 10px;">
<el-button :icon="Plus" @click="onAccessManage">成员</el-button> <el-button :icon="Plus" @click="onAccessManage">成员</el-button>
<el-button :icon="Plus" @click="onAiAgent">创建智能体</el-button> <el-button :icon="Plus" @click="onAiAgent">创建智能体</el-button>
<el-button :icon="Delete" @click="onDeleteSpace">删除</el-button> <!-- <el-button :icon="Delete" @click="onDeleteSpace">删除</el-button> -->
</el-button-group> </el-button-group>
</el-row> </el-row>
@ -517,8 +596,8 @@ function isOwner(){
<!-- <el-table-column type="selection" width="50" /> --> <!-- <el-table-column type="selection" width="50" /> -->
<el-table-column width="450" property="name" label="文件名"> <el-table-column width="450" property="name" label="文件名">
<template #default="scope"> <template #default="scope">
<input type="text" autofocus placeholder="文件夹名" style="border:groove;height:30px;" v-model="newdir" @change="onCreateDir" v-if="scope.row.name===''" /> <input v-if="scope.row.name===''" v-model="newdirName" type="text" autofocus placeholder="文件夹名" style="border:groove;height:30px;" @change="onCreateDir" />
<div v-if="scope.row.name" style="display: flex; align-items: center;"> <div v-else style="display: flex; align-items: center;">
<svg-icon v-if="scope.row.dir" icon-class="folder-icon" :size="30"/> <svg-icon v-if="scope.row.dir" icon-class="folder-icon" :size="30"/>
<el-image v-else-if="getFileIcon(scope.row.name)==='img'" style="width: 30px;" :preview-src-list="[getSpaceImageDURL(scope.row.uuid,scope.row.name)]" :src="getSpaceImageViewURL(scope.row.uuid,scope.row.name)" /> <el-image v-else-if="getFileIcon(scope.row.name)==='img'" style="width: 30px;" :preview-src-list="[getSpaceImageDURL(scope.row.uuid,scope.row.name)]" :src="getSpaceImageViewURL(scope.row.uuid,scope.row.name)" />
<svg-icon v-else :icon-class="getFileIcon(scope.row.name)+'-icon'" :size="30" /> <svg-icon v-else :icon-class="getFileIcon(scope.row.name)+'-icon'" :size="30" />
@ -526,14 +605,17 @@ function isOwner(){
</div> </div>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column width="250"> <el-table-column width="350">
<template #default="scope" > <template #default="scope" >
<el-tag v-if="scope.row.agent" effect="dark" size="small" type="success" round >智能体</el-tag> <el-tag v-if="scope.row.agent" effect="dark" size="small" type="success" round >智能体</el-tag>
<div v-show="currentHoverRow === scope.row.name" style="display:inline; margin-left:15px"> <div v-show="currentHoverRow === scope.row.name" style="display:inline; margin-left:15px">
<el-button size="small" :icon="Edit" circle @click="onlyOfficeEdit(scope.row)"></el-button> <el-button v-if="getFileIcon(scope.row.name)!='img'" size="small" :icon="View" circle @click="onPrivateView(scope.row)"></el-button>
<el-button size="small" :icon="View" circle @click="onPrivateView(scope.row)"></el-button> <el-button v-if="scope.row.permitVal>=PERMITS.DOWNLOAD" size="small" :icon="Download" circle @click="onDownload(scope.row)"></el-button>
<el-button size="small" :icon="Download" circle @click="onDownload(scope.row)"></el-button> <el-button v-if="scope.row.permitVal>=PERMITS.EDIT" size="small" :icon="Edit" circle @click="onlyOfficeEdit(scope.row)"></el-button>
<span v-if="scope.row.permitVal>=PERMITS.MANAGER" class="manager_span" >
<el-button size="small" :icon="Delete" circle @click="onDelMatter(scope.row)"></el-button> <el-button size="small" :icon="Delete" circle @click="onDelMatter(scope.row)"></el-button>
<el-button size="small" :icon="Setting" circle @click="onSpacePManage(scope.row)"></el-button>
</span>
</div> </div>
</template> </template>
</el-table-column> </el-table-column>
@ -549,7 +631,12 @@ function isOwner(){
<div class="table-grid" v-else> <div class="table-grid" v-else>
<div class="grid-item" v-for="row in matterList"> <div class="grid-item" v-for="row in matterList">
<div class="grid"> <div class="grid">
<div class="grid-box" @click="handleMouseEnter(row)"> <div v-if="row.name===''">
<svg-icon icon-class="folder-icon" size="80px"/>
<input v-model="newdirName" type="text" autofocus placeholder="文件夹名" style="border:groove;height:30px;" @change="onCreateDir" />
</div>
<div v-else class="grid-box" @mouseenter="handleMouseEnter(row)">
<svg-icon v-if="row.dir" icon-class="folder-icon" size="80px"/> <svg-icon v-if="row.dir" icon-class="folder-icon" size="80px"/>
<el-image v-else-if="getFileIcon(row.name)==='img'" style="width: 80px;" :preview-src-list="[getSpaceImageDURL(row.uuid,row.name)]" :src="getSpaceImageViewURL(row.uuid,row.name)" /> <el-image v-else-if="getFileIcon(row.name)==='img'" style="width: 80px;" :preview-src-list="[getSpaceImageDURL(row.uuid,row.name)]" :src="getSpaceImageViewURL(row.uuid,row.name)" />
<svg-icon v-else :icon-class="getFileIcon(row.name)+'-icon'" size="80px"/> <svg-icon v-else :icon-class="getFileIcon(row.name)+'-icon'" size="80px"/>
@ -557,11 +644,14 @@ function isOwner(){
<el-tag v-if="row.agent" effect="dark" size="small" type="success" round >智能体</el-tag> <el-tag v-if="row.agent" effect="dark" size="small" type="success" round >智能体</el-tag>
</div> </div>
</div> </div>
<div class="grid-menus" v-show="currentHoverRow === row.name"> <div v-if="row.name!=''" class="grid-menus" v-show="currentHoverRow === row.name">
<el-button size="small" :icon="Edit" circle @click="onlyOfficeEdit(row)"></el-button>
<el-button v-if="getFileIcon(row.name)!='img'" size="small" :icon="View" circle @click="onPrivateView(row)"></el-button> <el-button v-if="getFileIcon(row.name)!='img'" size="small" :icon="View" circle @click="onPrivateView(row)"></el-button>
<el-button size="small" :icon="Download" circle @click="onDownload(row)"></el-button> <el-button v-if="row.permitVal! >= PERMITS.DOWNLOAD" size="small" :icon="Download" circle @click="onDownload(row)"></el-button>
<el-button v-if="row.permitVal! >= PERMITS.EDIT" size="small" :icon="Edit" circle @click="onlyOfficeEdit(row)"></el-button>
<span v-if="row.permitVal! >= PERMITS.MANAGER" >
<el-button size="small" :icon="Delete" circle @click="onDelMatter(row)"></el-button> <el-button size="small" :icon="Delete" circle @click="onDelMatter(row)"></el-button>
<el-button size="small" :icon="Setting" circle @click="onSpacePManage(row)"></el-button>
</span>
</div> </div>
</div> </div>
</div> </div>
@ -620,6 +710,10 @@ function isOwner(){
} }
} }
.manager_span{
margin-left: 10px;
}
.dynamic-width-message-box-byme .el-message-box__message{ .dynamic-width-message-box-byme .el-message-box__message{
width: 100%; width: 100%;
} }

348
src/views/doc/spacePermission.vue

@ -0,0 +1,348 @@
<script lang="ts" setup>
import {
resetSpaceMatterPermit,
getSpaceMemberList,
addSpaceManager,
updateSpaceMetterPermit,
} from '@/api/hr/people/share_ctrol'
import { ElDialog, ElMessageBox,ElStep,TreeInstance} from 'element-plus';
import { useOrgMemberStore } from "@/store/modules/orgMember";
const props = withDefaults(defineProps<{
uid:string, //uuid
uuid:string, //uuid
suid:string, //
spaceid:string, //uuid
closeFunc:(refresh?:boolean)=>void, //
}>(),{})
const orgMembers = useOrgMemberStore()
const spacePermit=ref<{id:number,data:string,matterUid:string}>({}) //
const treeRef=ref<TreeInstance>() //tree
const managerMode=ref(false)
const managers=ref<string[]>([])
let resultPermits: Record<string, number> = {};
interface Tree {
id: string
label:string
parentId?:string
indeterminate?:boolean,
radio?:number[];
children?: Tree[]
ismanager?:boolean,
}
const dataSource = ref<Tree[]>([])
//
async function onSavePermChange(){
resultPermits={}
//
if (managerMode.value){
managers.value=[] //
dataSource.value.forEach(item=>{
if(item.ismanager){
managers.value.push("p0"+item.id)
}
if(item.children) collectManager(item)
})
await addSpaceManager(btoa(props.uid),{
space:props.spaceid,
mangers:managers.value.join("|")
}).then(resp=>{
console.log(resp)
})
props.closeFunc()
return
}
dataSource.value.forEach(item=>{
if(item.radio&&item.radio.length>0){
if(item.indeterminate) {
item.radio[0]+=10
}
resultPermits[item.id]=item.radio[0]
}
if(item.children) collectNodePermits(item)
})
spacePermit.value.data=JSON.stringify(resultPermits)
updateSpaceMetterPermit(btoa(props.uid),{
space:props.spaceid,
matter:props.uuid,
permits:spacePermit.value
}).then(resp=>{
console.log(resp)
})
props.closeFunc()
}
function collectManager(node:Tree){
node.children?.forEach(ele => {
if(ele.ismanager){
managers.value.push("p0"+ele.id)
}
if(ele.children) collectManager(ele)
});
}
//
function collectNodePermits(node:Tree){
node.children?.forEach(ele => {
if(ele.radio&&ele.radio.length>0){
if(ele.indeterminate) {
ele.radio[0]+=10
}
resultPermits[ele.id]=ele.radio[0]
}
if(ele.children){
collectNodePermits(ele)
}
});
}
//
function onGroupValueChange(node:Tree, val:number[]){
if(node.indeterminate) node.indeterminate=false;
node.children?.forEach(ele => {
ele.radio=val
if(ele.children){
onGroupValueChange(ele,val)
}
});
if(node.parentId){
updateParentNode(node)
}
}
//
function updateParentNode(node:Tree){
if(node.parentId){
const pnode = treeRef.value?.getNode(node.parentId);
if(pnode){
const tdata=pnode.data as Tree
if (tdata.children?.every(ele=>{
if(ele.indeterminate) return !ele.indeterminate;//
if(ele.radio?.length==0) return ele.radio.length==tdata.radio?.length;
return ele.radio?.length==tdata.radio?.length && ele.radio[0]==tdata.radio[0]
})) {
tdata.indeterminate=false
}else{
tdata.indeterminate=true
}
updateParentNode(tdata)
}
}
}
//
function delMatterPermit(matter_uuid:string){
resetSpaceMatterPermit(btoa(props.uid),{
space:props.spaceid,
matter:matter_uuid,
}).then(()=>{
refreshSpaceData()
})
}
function onShowManagers(){
managers.value.forEach(item=>{
const node = treeRef.value?.getNode(item.replace("p0",""));
if(node && node.data){
node.data.ismanager=true
}
})
}
function refreshSpaceData(){
getSpaceMemberList(
btoa(props.uid),
{space:props.spaceid,matter:props.uuid}
).then(resp=>{
resp.data?.dprts?.forEach(item=>{
for(let data of dataSource.value){
if (data.id==item) return;
if (checkNode(item,data)) return;
}
addNode(item,orgMembers.dataTree)
});
resp.data?.members?.forEach(item=>{
const mid=item.replace("p0","")
for(let data of dataSource.value){
if(checkNode(mid,data)) return;
}
dataSource.value.push({id:mid,label:orgMembers.listMap[mid],radio:[2]})
});
managers.value=resp.data?.managers.split("|")
spacePermit.value.id=resp.data?.permits.ID
spacePermit.value.matterUid=resp.data?.permits.MatterUuid
spacePermit.value.data=resp.data.permits.data!="" ? resp.data.permits.data : "{}"
nextTick(() => {
const permitJson = JSON.parse(spacePermit.value.data) //object
Object.keys(permitJson).forEach(key=>{
const node = treeRef.value?.getNode(key);
if(node && node.data){
if(permitJson[key]>10){
node.data.radio = [permitJson[key]%10]
node.data.indeterminate=true
}else{
node.data.radio = [permitJson[key]]
}
}
})
});
})
}
function addNode(key:string,node:Tree){
node.children?.forEach(ele => {
if(ele.id==key){
const eleClone=structuredClone(toRaw(ele)) //eleProxyclonetoRawobject
eleClone.radio=[2]
eleClone.parentId=ele.parentId
dataSource.value.push(eleClone) //{id:ele.id,label:ele.label,radio:2,stage:level,children:ele.children}
return
}
if(ele.children){
addNode(key,ele)
}
});
}
function checkNode(key:string,node:Tree):boolean{
for (const child of node.children||[]) {
if(child.id==key){
return true
}
if(child.children){
//returnreturnfortruereturn
if(checkNode(key,child)) return true;
}
}
return false;
}
onMounted(()=>{
refreshSpaceData()
})
</script>
<template>
<el-dialog :model-value="true" :style="{'max-height': '750px'}" v-on:close="closeFunc()">
<template #header>
<el-button link @click="managerMode=false;">文档权限管理</el-button>
<el-button v-if="spacePermit.matterUid==spaceid&&uid==suid" link @click="managerMode=true; onShowManagers()">管理员管理</el-button>
</template>
<div v-if="uuid==spacePermit.matterUid&&uuid!=spaceid" class="tips">当前文档存在定制权限,与空间权限不一致。<el-button size="small" @click="delMatterPermit(uuid)">恢复</el-button></div>
<div class="tree-node" style="width:93%;font-weight: bold;position: sticky;">
<span style="width: 200px;text-align: center;">名称</span>
<div v-if="managerMode" class="buttons">
<span>管理员</span>
</div>
<div v-else class="buttons">
<span>禁止</span>
<span>仅预览</span>
<span>可下载</span>
<span>上传下载</span>
<span>编辑</span>
</div>
</div>
<div class="tablelist">
<el-tree
ref="treeRef"
:data="dataSource"
node-key="id"
default-expand-all
:expand-on-click-node="false"
>
<template #default="{ node, data }">
<div class="tree-node">
<span>{{ node.label }}</span>
<div v-if="managerMode" class="buttons">
<el-checkbox v-if="!data.children" v-model="data.ismanager" />
</div>
<div v-else class="buttons">
<el-checkbox-group :min="0" :max="1" v-model="data.radio" @change="(val)=>onGroupValueChange(data,val)">
<el-checkbox key="forbid" :indeterminate="data.indeterminate" :value="0" />
<el-checkbox key="view" :indeterminate="data.indeterminate" :value="1" />
<el-checkbox key="download" :indeterminate="data.indeterminate" :value="2" />
<el-checkbox key="updown" :indeterminate="data.indeterminate" :value="3" />
<el-checkbox key="edit" :indeterminate="data.indeterminate" :value="4" />
</el-checkbox-group>
</div>
</div>
</template>
</el-tree>
</div>
<template #footer>
<div class="dialog-footer">
<el-button @click="closeFunc()">取消</el-button>
<el-button type="primary" @click="onSavePermChange">保存</el-button>
</div>
</template>
</el-dialog>
</template>
<style lang="scss" scoped>
.tablelist{
width: 94%;
height: 565px;
overflow-y: scroll
}
.tips{
display: flex;
align-items: center;
margin: 5px;
padding: 5px 32px;
background-color: #d7d1ca;
}
.tree-node{
display: flex;
flex-direction: row;
width: 100%;
align-items: center;
.buttons{
margin: 0 50px 0 auto;
span{
width: 26px;
margin: 0 7px;
}
}
}
.el-checkbox{
width: 26px;
}
.el-tree{
/* 让整个弹出窗口位置更高一些*/
--el-tree-node-content-height:33px;
}
</style>
Loading…
Cancel
Save